Example #1
0
 def get_node_log_v2(self, history_id: int) -> dict:
     runtime = BambooDjangoRuntime()
     return {
         "result": True,
         "data": handle_plain_log(runtime.get_plain_log_for_node(node_id=self.node_id, history_id=history_id)),
         "message": "",
     }
Example #2
0
    def callback_v2(self, operator: str, **kwargs) -> dict:
        # 兼容 pipeline 引擎时期 callback 可以不传 version 的请求
        runtime = BambooDjangoRuntime()
        version = kwargs.get("version")
        if not version:
            version = runtime.get_state(self.node_id).version

        return bamboo_engine_api.callback(runtime=runtime, node_id=self.node_id, version=version, data=kwargs["data"])
Example #3
0
 def skip_cpg_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.skip_conditional_parallel_gateway(
         runtime=BambooDjangoRuntime(),
         node_id=self.node_id,
         flow_ids=kwargs["flow_ids"],
         converge_gateway_id=kwargs["converge_gateway_id"],
     )
Example #4
0
    def render_current_constants_v2(self):
        runtime = BambooDjangoRuntime()
        context_values = runtime.get_context(
            self.pipeline_instance.instance_id)
        try:
            root_pipeline_inputs = {
                key: di.value
                for key, di in runtime.get_data_inputs(
                    self.pipeline_instance.instance_id).items()
            }
        except bamboo_engine_exceptions.NotFoundError:
            return {
                "result": False,
                "data": None,
                "code": err_code.CONTENT_NOT_EXIST.code,
                "message": "data not found, task is not running",
            }
        context = Context(runtime, context_values, root_pipeline_inputs)

        try:
            hydrated_context = context.hydrate()
        except Exception as e:
            logger.exception(
                "[render_current_constants_v2] error occurred at context hydrate"
            )
            return {
                "result": False,
                "data": None,
                "code": err_code.UNKNOWN_ERROR.code,
                "message": "context hydrate error: %s" % str(e),
            }

        data = []
        for key, value in hydrated_context.items():
            if isinstance(value, SystemObject):
                data.append({"key": key, "value": value.__dict__})
            else:
                data.append({"key": key, "value": value})

        return {
            "result": True,
            "data": data,
            "code": err_code.SUCCESS.code,
            "message": ""
        }
Example #5
0
 def task_pause(self):
     """
        手动暂停正在运行的pipeline任务
     """
     pause_info = api.pause_pipeline(runtime=BambooDjangoRuntime(),
                                     pipeline_id=self.pipeline_id)
     if not pause_info.result:
         logger.error("暂停任务失败,错误信息:{},pipeline_id :{}".format(
             pause_info.exc, self.pipeline_id))
     return pause_info.result
Example #6
0
 def task_resume(self):
     """
         手动启动已暂停的pipeline任务
     """
     resume_info = api.resume_pipeline(runtime=BambooDjangoRuntime(),
                                       pipeline_id=self.pipeline_id)
     if not resume_info.result:
         logger.error("重新启动任务失败,错误信息:{},pipeline_id :{}".format(
             resume_info.exc, self.pipeline_id))
     return resume_info.result
Example #7
0
 def get_task_states(self):
     """
         根据pipeline_id 获取流程树状态
     """
     if self.pipeline_id:
         data = api.get_pipeline_states(runtime=BambooDjangoRuntime(),
                                        root_id=self.pipeline_id).data
         return data
     else:
         return None
Example #8
0
 def get_node_output(self):
     """
        根据node_id 获取活动节点的输出日志
     """
     if self.node_id:
         data = api.get_execution_data_outputs(
             runtime=BambooDjangoRuntime(),
             node_id=self.node_id).data.get('result_message', 'running')
         return data
     else:
         logger.error("no node_id")
         return None
Example #9
0
    def get_outputs_v2(self):
        runtime = BambooDjangoRuntime()
        outputs_result = bamboo_engine_api.get_execution_data_outputs(runtime=runtime, node_id=self.node_id)

        if not outputs_result.result:
            logger.exception("bamboo_engine_api.get_execution_data_outputs fail")
            return {
                "result": False,
                "data": {},
                "message": "{}: {}".format(outputs_result.message, outputs_result.exc),
                "code": err_code.UNKNOWN_ERROR.code,
            }

        return {"result": True, "data": outputs_result.data, "message": "", "code": err_code.SUCCESS.code}
Example #10
0
    def build_bamboo(self):
        """
           build_bamboo方法:建立流程任务
        """

        self.pipe.extend(self.end_act)
        bamboo_task = build_tree(self.start_act, data=self.global_data)
        update_record_detail(self.task_id, {"pipeline_id": bamboo_task['id']})
        update_record_detail(self.task_id, {"pipeline_tree": json.dumps(self.act_tree)})

        if not api.run_pipeline(runtime=BambooDjangoRuntime(), pipeline=bamboo_task).result:
            logger.error("部署bamboo流程任务创建失败,任务结束")
            return False

        return True
Example #11
0
def _ensure_node_can_retry(node_id, engine_ver):
    count = 0
    while count < 3:
        if engine_ver == EngineConfig.ENGINE_VER_V1:
            if PipelineProcess.objects.filter(current_node_id=node_id,
                                              is_sleep=True).exists():
                return True
        elif engine_ver == EngineConfig.ENGINE_VER_V2:
            if BambooDjangoRuntime(
            ).get_sleep_process_info_with_current_node_id(node_id):
                return True
        else:
            raise ValueError("invalid engine_ver: %s" % engine_ver)

        time.sleep(0.1)
        count += 1

    return False
Example #12
0
    def start_v2(self, executor: str) -> dict:
        # CAS
        update_success = PipelineInstance.objects.filter(
            instance_id=self.pipeline_instance.instance_id,
            is_started=False).update(start_time=timezone.now(),
                                     is_started=True,
                                     executor=executor)
        self.pipeline_instance.calculate_tree_info()
        PipelineInstance.objects.filter(
            instance_id=self.pipeline_instance.instance_id).update(
                tree_info_id=self.pipeline_instance.tree_info.id)

        if not update_success:
            return {
                "result": False,
                "message": "task already started",
                "code": err_code.INVALID_OPERATION.code
            }

        try:
            # convert web pipeline to pipeline
            pipeline = format_web_data_to_pipeline(
                self.pipeline_instance.execution_data)

            root_pipeline_data = get_pipeline_context(self.pipeline_instance,
                                                      obj_type="instance",
                                                      data_type="data",
                                                      username=executor)
            system_obj = SystemObject(root_pipeline_data)
            root_pipeline_context = {"${_system}": system_obj}
            root_pipeline_context.update(
                get_project_constants_context(self.project_id))

            # run pipeline
            result = bamboo_engine_api.run_pipeline(
                runtime=BambooDjangoRuntime(),
                pipeline=pipeline,
                root_pipeline_data=root_pipeline_data,
                root_pipeline_context=root_pipeline_context,
                subprocess_context=root_pipeline_context,
                queue=self.queue,
                cycle_tolerate=True,
            )
        except Exception as e:
            logger.exception("run pipeline failed")
            PipelineInstance.objects.filter(
                instance_id=self.pipeline_instance.instance_id,
                is_started=True).update(
                    start_time=None,
                    is_started=False,
                    executor="",
                )
            return {
                "result": False,
                "message": "run pipeline failed: {}".format(e),
                "code": err_code.UNKNOWN_ERROR.code,
            }

        if not result.result:
            PipelineInstance.objects.filter(
                instance_id=self.pipeline_instance.instance_id,
                is_started=True).update(
                    start_time=None,
                    is_started=False,
                    executor="",
                )
            logger.error("run_pipeline fail: {}, exception: {}".format(
                result.message, result.exc_trace))
        else:
            taskflow_started.send(sender=self.__class__,
                                  task_id=self.taskflow_id)

        dict_result = {
            "result":
            result.result,
            "message":
            result.message,
            "code":
            err_code.SUCCESS.code
            if result.result else err_code.UNKNOWN_ERROR.code,
        }

        return dict_result
Example #13
0
 def resume_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.resume_node_appoint(runtime=BambooDjangoRuntime(), node_id=self.node_id)
Example #14
0
 def resume_subproc_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.resume_pipeline(runtime=BambooDjangoRuntime(), pipeline_id=self.node_id)
Example #15
0
 def forced_fail_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.forced_fail_activity(
         runtime=BambooDjangoRuntime(), node_id=self.node_id, ex_data="forced fail by {}".format(operator)
     )
Example #16
0
 def retry_subprocess_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.retry_subprocess(runtime=BambooDjangoRuntime(), node_id=self.node_id)
Example #17
0
    def get(self, request, project_id, task_id, node_id, version):
        runtime = BambooDjangoRuntime()
        logs = handle_plain_log(runtime.get_plain_log_for_node(node_id=node_id, version=version))

        return Response({"result": True, "message": "success", "data": logs})
Example #18
0
 def skip_exg_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.skip_exclusive_gateway(
         runtime=BambooDjangoRuntime(), node_id=self.node_id, flow_id=kwargs["flow_id"]
     )
Example #19
0
    def get_node_data_v2(
        self,
        username: str,
        subprocess_stack: List[str],
        component_code: Optional[str] = None,
        loop: Optional[int] = None,
        **kwargs,
    ) -> dict:
        runtime = BambooDjangoRuntime()
        result = bamboo_engine_api.get_children_states(runtime=runtime, node_id=self.node_id)
        if not result.result:
            logger.exception("bamboo_engine_api.get_children_states fail")
            return {
                "result": False,
                "data": {},
                "message": "{}: {}".format(result.message, result.exc),
                "code": err_code.UNKNOWN_ERROR.code,
            }

        state = result.data
        # 已执行的节点直接获取执行数据
        inputs = {}
        outputs = {}
        pipeline_instance = kwargs["pipeline_instance"]

        if state:
            # 获取最新的执行数据
            if loop is None or int(loop) >= state[self.node_id]["loop"]:
                result = bamboo_engine_api.get_execution_data(runtime=runtime, node_id=self.node_id)
                if not result.result:
                    logger.exception("bamboo_engine_api.get_execution_data fail")

                    # 对上层屏蔽执行数据不存在的场景
                    if isinstance(result.exc, bamboo_exceptions.NotFoundError):
                        return {
                            "result": True,
                            "data": {"inputs": {}, "outputs": [], "ex_data": ""},
                            "message": "",
                            "code": err_code.SUCCESS.code,
                        }
                    else:
                        return {
                            "result": False,
                            "data": {},
                            "message": "{}: {}".format(result.message, result.exc),
                            "code": err_code.UNKNOWN_ERROR.code,
                        }

                data = result.data
                inputs = data["inputs"]
                outputs = data["outputs"]
                outputs = {"outputs": outputs, "ex_data": outputs.get("ex_data")}
            # 读取历史记录
            else:
                result = bamboo_engine_api.get_node_histories(runtime=runtime, node_id=self.node_id, loop=loop)
                if not result.result:
                    logger.exception("bamboo_engine_api.get_node_histories fail")
                    return {
                        "result": False,
                        "data": {},
                        "message": "{}: {}".format(result.message, result.exc),
                        "code": err_code.UNKNOWN_ERROR.code,
                    }

                hist = result.data
                if hist:
                    inputs = hist[-1]["inputs"]
                    outputs = hist[-1]["outputs"]
                    outputs = {"outputs": outputs, "ex_data": outputs.get("ex_data")}
        # 未执行节点需要实时渲染
        else:
            node_info = self._get_node_info(
                node_id=self.node_id, pipeline=pipeline_instance.execution_data, subprocess_stack=subprocess_stack
            )
            if node_info["type"] != "ServiceActivity":
                return {
                    "result": True,
                    "data": {"inputs": {}, "outputs": [], "ex_data": ""},
                    "message": "",
                    "code": err_code.SUCCESS.code,
                }
            try:
                root_pipeline_data = get_pipeline_context(
                    pipeline_instance, obj_type="instance", data_type="data", username=username
                )
                system_obj = SystemObject(root_pipeline_data)
                root_pipeline_context = {"${_system}": {"type": "plain", "value": system_obj}}
                root_pipeline_context.update(
                    {
                        key: {"type": "plain", "value": value}
                        for key, value in get_project_constants_context(kwargs["project_id"]).items()
                    }
                )

                formatted_pipeline = format_web_data_to_pipeline(pipeline_instance.execution_data)
                preview_result = bamboo_engine_api.preview_node_inputs(
                    runtime=runtime,
                    pipeline=formatted_pipeline,
                    node_id=self.node_id,
                    subprocess_stack=subprocess_stack,
                    root_pipeline_data=root_pipeline_data,
                    parent_params=root_pipeline_context,
                )

                if not preview_result.result:
                    return {
                        "result": False,
                        "data": {},
                        "message": preview_result.message,
                        "code": err_code.UNKNOWN_ERROR.code,
                    }
                inputs = preview_result.data

            except Exception as err:
                return {
                    "result": False,
                    "data": {},
                    "message": err,
                    "code": err_code.UNKNOWN_ERROR.code,
                }

        # 根据传入的 component_code 对输出进行格式化
        success, err, outputs_table = self._format_outputs(
            outputs=outputs,
            component_code=component_code,
            pipeline_instance=pipeline_instance,
            subprocess_stack=subprocess_stack,
        )
        if not success:
            return {
                "result": False,
                "data": {},
                "message": err,
                "code": err_code.UNKNOWN_ERROR.code,
            }

        data = {"inputs": inputs, "outputs": outputs_table, "ex_data": outputs.pop("ex_data", "")}
        return {
            "result": True,
            "data": data,
            "message": "",
            "code": err_code.SUCCESS.code,
        }
Example #20
0
 def revoke_v2(self, operator: str) -> dict:
     return bamboo_engine_api.revoke_pipeline(
         runtime=BambooDjangoRuntime(),
         pipeline_id=self.pipeline_instance.instance_id)
Example #21
0
    def get_node_detail_v2(
        self,
        username: str,
        subprocess_stack: List[str],
        component_code: Optional[str] = None,
        loop: Optional[int] = None,
        **kwargs,
    ) -> dict:
        runtime = BambooDjangoRuntime()
        result = bamboo_engine_api.get_children_states(runtime=runtime, node_id=self.node_id)
        if not result.result:
            logger.exception("bamboo_engine_api.get_children_states fail")
            return {
                "result": False,
                "data": {},
                "message": "{}: {}".format(result.message, result.exc),
                "code": err_code.UNKNOWN_ERROR.code,
            }

        detail = result.data
        # 节点已经执行
        if detail:
            detail = detail[self.node_id]
            # 默认只请求最后一次循环结果
            format_pipeline_status(detail)
            if loop is None or int(loop) >= detail["loop"]:
                loop = detail["loop"]
                hist_result = bamboo_engine_api.get_node_histories(runtime=runtime, node_id=self.node_id, loop=loop)
                if not hist_result:
                    logger.exception("bamboo_engine_api.get_node_histories fail")
                    return {
                        "result": False,
                        "data": {},
                        "message": "{}: {}".format(hist_result.message, hist_result.exc),
                        "code": err_code.UNKNOWN_ERROR.code,
                    }
                for hist in hist_result.data:
                    hist["ex_data"] = hist.get("outputs", {}).get("ex_data", "")
                detail["histories"] = hist_result.data
                detail["history_id"] = -1
            # 如果用户传了 loop 参数,并且 loop 小于当前节点已循环次数,则从历史数据获取结果
            else:
                hist_result = bamboo_engine_api.get_node_histories(runtime=runtime, node_id=self.node_id, loop=loop)
                if not hist_result:
                    logger.exception("bamboo_engine_api.get_node_histories fail")
                    return {
                        "result": False,
                        "data": {},
                        "message": "{}: {}".format(hist_result.message, hist_result.exc),
                        "code": err_code.UNKNOWN_ERROR.code,
                    }
                self._assemble_histroy_detail(detail=detail, histories=hist_result.data)
                detail["history_id"] = hist_result.data[-1]["id"]
                detail["version"] = hist_result.data[-1]["version"]

            for hist in detail["histories"]:
                # 重试记录必然是因为失败才重试
                hist.setdefault("state", bamboo_engine_states.FAILED)
                hist["history_id"] = hist["id"]
                format_pipeline_status(hist)
        # 节点未执行
        else:
            pipeline_instance = kwargs["pipeline_instance"]
            node = self._get_node_info(
                node_id=self.node_id, pipeline=pipeline_instance.execution_data, subprocess_stack=subprocess_stack
            )
            detail.update(
                {
                    "name": node["name"],
                    "error_ignorable": node.get("error_ignorable", False),
                    "state": bamboo_engine_states.READY,
                }
            )

        return {"result": True, "data": detail, "message": "", "code": err_code.SUCCESS.code}
Example #22
0
    def get_task_status_v2(self, subprocess_id: Optional[str],
                           with_ex_data: bool) -> dict:
        if self.pipeline_instance.is_expired:
            return {
                "result": True,
                "data": {
                    "state": "EXPIRED"
                },
                "message": "",
                "code": err_code.SUCCESS.code
            }
        if not self.pipeline_instance.is_started:
            return {
                "result": True,
                "data": self.CREATED_STATUS,
                "message": "",
                "code": err_code.SUCCESS.code,
            }

        runtime = BambooDjangoRuntime()
        status_result = bamboo_engine_api.get_pipeline_states(
            runtime=runtime,
            root_id=self.pipeline_instance.instance_id,
            flat_children=False)
        if not status_result:
            logger.exception("bamboo_engine_api.get_pipeline_states fail")
            return {
                "result":
                False,
                "data": {},
                "message":
                "{}: {}".format(status_result.message, status_result.exc),
                "code":
                err_code.UNKNOWN_ERROR.code,
            }
        task_status = status_result.data
        if not task_status:
            return {
                "result": True,
                "data": self.CREATED_STATUS,
                "message": "",
                "code": err_code.SUCCESS.code,
            }
        task_status = task_status[self.pipeline_instance.instance_id]

        def get_subprocess_status(task_status: dict,
                                  subprocess_id: str) -> dict:
            for child in task_status["children"].values():
                if child["id"] == subprocess_id:
                    return child
                if child["children"]:
                    status = get_subprocess_status(child, subprocess_id)
                    if status is not None:
                        return status

        if subprocess_id:
            task_status = get_subprocess_status(task_status, subprocess_id)

        # subprocess not been executed
        task_status = task_status or self.CREATED_STATUS

        format_bamboo_engine_status(task_status)

        # 返回失败节点和对应调试信息
        if with_ex_data and task_status["state"] == bamboo_engine_states.FAILED:
            failed_nodes = self._collect_fail_nodes(task_status)
            task_status["ex_data"] = {}
            for node_id in failed_nodes:
                data_result = bamboo_engine_api.get_execution_data_outputs(
                    runtime=runtime, node_id=node_id)

                if not data_result:
                    task_status["ex_data"][
                        node_id] = "get ex_data fail: {}".format(
                            data_result.exc)
                else:
                    task_status["ex_data"][node_id] = data_result.data.get(
                        "ex_data")

        return {
            "result": True,
            "data": task_status,
            "code": err_code.SUCCESS.code,
            "message": ""
        }
Example #23
0
 def retry_v2(self, operator: str, **kwargs) -> dict:
     # 数据为空的情况传入 None, v2 engine api 不认为 {} 是空数据
     return bamboo_engine_api.retry_node(
         runtime=BambooDjangoRuntime(), node_id=self.node_id, data=kwargs["inputs"] or None
     )
Example #24
0
def recursive_collect_components_execution(activities,
                                           status_tree,
                                           task_instance,
                                           engine_ver=1,
                                           stack=None):
    """
    @summary 递归流程树,获取所有执行结束的插件TaskflowExecutedNodeStatistics对象列表(成功/失败)
    @param activities: 当前流程树的任务节点信息
    @param status_tree: 当前流程树的任务节点状态
    @param task_instance: 根流程实例TaskFlowInstance
    @param stack: 子流程堆栈
    @param engine_ver: 流程引擎版本
    """
    instance = task_instance.pipeline_instance
    task_instance_id = task_instance.id
    task_template = TaskTemplate.objects.get(
        pipeline_template=instance.template)
    if stack is None:
        stack = []
        is_sub = False
    else:
        is_sub = True
    component_list = []
    for act_id, act in activities.items():
        if act_id in status_tree:
            exec_act = status_tree[act_id]
            # 标准插件节点
            if act[PE.type] == PE.ServiceActivity:
                # 结束、失败、撤销
                if exec_act["state"] in states.ARCHIVED_STATES:
                    component_code = act["component"]["code"]
                    component_version = act["component"].get(
                        "version", LEGACY_PLUGINS_VERSION)
                    is_remote = False
                    if component_code == "remote_plugin":
                        component_code = act["component"]["data"][
                            "plugin_code"]["value"]
                        component_version = act["component"]["data"][
                            "plugin_version"]["value"]
                        is_remote = True
                    component_kwargs = {
                        "component_code":
                        component_code,
                        "instance_id":
                        instance.id,
                        "task_instance_id":
                        task_instance_id,
                        "is_sub":
                        is_sub,
                        "node_id":
                        act_id,
                        "subprocess_stack":
                        json.dumps(stack),
                        "started_time":
                        format_date_time(exec_act["start_time"]),
                        "archived_time":
                        format_date_time(exec_act["finish_time"]),
                        "elapsed_time":
                        exec_act.get(
                            "elapsed_time",
                            calculate_elapsed_time(
                                format_date_time(exec_act["start_time"]),
                                format_date_time(exec_act["finish_time"])),
                        ),
                        "is_skip":
                        exec_act["skip"],
                        "is_retry":
                        False,
                        "status":
                        exec_act["state"] == "FINISHED",
                        "version":
                        component_version,
                        "template_id":
                        instance.template.id,
                        "task_template_id":
                        task_template.id,
                        "project_id":
                        task_template.project.id,
                        "instance_create_time":
                        instance.create_time,
                        "instance_start_time":
                        instance.start_time,
                        "instance_finish_time":
                        instance.finish_time,
                        "is_remote":
                        is_remote,
                    }
                    component_list.append(
                        TaskflowExecutedNodeStatistics(**component_kwargs))
                    if exec_act["retry"] > 0:
                        # 有重试记录,需要从执行历史中获取数据
                        if engine_ver == 1:
                            history_list = pipeline_api.get_activity_histories(
                                act_id)
                        else:
                            history_list_result = bamboo_engine_api.get_node_short_histories(
                                runtime=BambooDjangoRuntime(), node_id=act_id)
                            history_list = history_list_result.data if history_list_result.result else []

                        for history in history_list:
                            component_kwargs.update({
                                "started_time":
                                history["started_time"],
                                "archived_time":
                                history["archived_time"],
                                "elapsed_time":
                                history.get(
                                    "elapsed_time",
                                    calculate_elapsed_time(
                                        history["started_time"],
                                        history["archived_time"]),
                                ),
                                "is_retry":
                                True,
                                "is_skip":
                                False,
                                "status":
                                False,
                            })
                            component_list.append(
                                TaskflowExecutedNodeStatistics(
                                    **component_kwargs))
            # 子流程的执行堆栈(子流程的执行过程)
            elif act[PE.type] == PE.SubProcess:
                sub_activities = act[PE.pipeline][PE.activities]
                # 防止stack共用
                copied_stack = deepcopy(stack)
                copied_stack.insert(0, act_id)
                component_list += recursive_collect_components_execution(
                    activities=sub_activities,
                    status_tree=exec_act["children"],
                    task_instance=task_instance,
                    stack=copied_stack,
                    engine_ver=engine_ver,
                )
    return component_list
Example #25
0
 def skip_v2(self, operator: str, **kwargs) -> dict:
     return bamboo_engine_api.skip_node(runtime=BambooDjangoRuntime(), node_id=self.node_id)