Exemple #1
0
    def obj_create(self, bundle, **kwargs):
        try:
            project_id = bundle.data.pop("project__id")
            template_id = bundle.data.pop("template_id")
            common_template = CommonTemplate.objects.get(pk=template_id)
        except Exception:
            raise BadRequest("common template does not exist")

        allow_or_raise_immediate_response(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", bundle.request.user.username),
            action=Action(IAMMeta.COMMON_FLOW_EDIT_ACTION),
            resources=res_factory.resources_for_common_flow_obj(
                common_template),
        )

        bundle.data["name"] = standardize_name(bundle.data["name"],
                                               TEMPLATE_NODE_NAME_MAX_LENGTH)
        kwargs["unique_id"] = "%s-%s-%s" % (project_id, template_id,
                                            bundle.data["name"])
        if TemplateScheme.objects.filter(
                unique_id=kwargs["unique_id"]).exists():
            raise BadRequest(
                "common template scheme name has existed, please change the name"
            )
        kwargs["template"] = common_template.pipeline_template
        return super(CommonTemplateSchemeResource,
                     self).obj_create(bundle, **kwargs)
Exemple #2
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,
    }
Exemple #3
0
    def obj_create(self, bundle, **kwargs):
        try:
            template_id = bundle.data.pop("template_id")
            project_id = bundle.data.pop("project__id")
            json.loads(bundle.data["data"])
        except Exception as e:
            message = "create scheme params error: %s" % e
            logger.error(message)
            raise BadRequest(message)
        _, template = self._check_user_scheme_permission(bundle.request.user.username, template_id, project_id)

        bundle.data["name"] = standardize_name(bundle.data["name"], TEMPLATE_NODE_NAME_MAX_LENGTH)
        kwargs["unique_id"] = "{}-{}".format(template_id, bundle.data["name"])
        if TemplateScheme.objects.filter(unique_id=kwargs["unique_id"]).exists():
            raise BadRequest("template scheme name has existed, please change the name")
        kwargs["template"] = template.pipeline_template
        return super(TemplateSchemeResource, self).obj_create(bundle, **kwargs)
Exemple #4
0
 def handle_task_name_attr(data):
     data["name"] = standardize_name(data["name"], TASK_NAME_MAX_LENGTH)
     standardize_pipeline_node_name(data["pipeline_tree"])
Exemple #5
0
    def save_app_maker(self, project_id, app_params, fake=False):
        """
        @summary:
        @param project_id: 项目 ID
        @param app_params: App maker参数
        @param fake: 为True则不会真正调用API创建轻应用
        @return:
        """
        from gcloud.iam_auth import res_factory

        logger.info("save_app_maker params: %s" % app_params)
        app_id = app_params["id"]
        if app_id == "0" or not app_id:
            app_id = None
        template_id = app_params["template_id"]
        app_params["name"] = standardize_name(app_params["name"], 20)
        app_params["desc"] = standardize_name(app_params.get("desc", ""), 30)
        proj = Project.objects.get(id=project_id)
        try:
            task_template = TaskTemplate.objects.get(pk=template_id,
                                                     project_id=project_id,
                                                     is_deleted=False)
        except TaskTemplate.DoesNotExist:
            return False, _("保存失败,引用的流程模板不存在!")

        if not app_id:
            subject = Subject("user", app_params["username"])
            action = Action(IAMMeta.FLOW_CREATE_MINI_APP_ACTION)
            resources = res_factory.resources_for_flow_obj(task_template)

            allow_or_raise_auth_failed(iam=iam,
                                       system=IAMMeta.SYSTEM_ID,
                                       subject=subject,
                                       action=action,
                                       resources=resources)

            fields = {
                "project": proj,
                "name": app_params["name"],
                "code": "",
                "desc": app_params["desc"],
                "logo_url": "",
                "link": app_params["link_prefix"],
                "creator": app_params["username"],
                "editor": app_params["username"],
                "task_template": task_template,
                # 生成一个删除状态的对象,以便拼接轻应用访问链接
                "is_deleted": True,
            }
            if app_params.get("category"):
                fields["category"] = app_params["category"]
            if app_params.get("template_scheme_id"):
                fields["template_scheme_id"] = app_params["template_scheme_id"]
            app_maker_obj = AppMaker.objects.create(**fields)

            # update app link
            app_id = app_maker_obj.id
            app_link = "{appmaker_prefix}{app_id}/newtask/{project_id}/selectnode/?template_id={template_id}".format(
                appmaker_prefix=app_params["link_prefix"],
                app_id=app_id,
                project_id=project_id,
                template_id=template_id)
            app_maker_obj.link = app_link

            if fake:
                app_maker_obj.code = "%s%s" % (settings.APP_CODE,
                                               time_now_str())
                app_maker_obj.is_deleted = False
                app_maker_obj.save()
                return True, app_maker_obj

            # create app on blueking desk
            app_create_result = create_maker_app(
                app_params["username"],
                app_params["name"],
                app_link,
                app_params["username"],
                app_params.get("category") or task_template.category,
                app_params["desc"],
            )
            if not app_create_result["result"]:
                return False, _("创建轻应用失败:%s") % app_create_result["message"]

            app_code = app_create_result["data"]["bk_light_app_code"]
            app_maker_obj.code = app_code
            app_maker_obj.is_deleted = False

        # edit appmaker
        else:
            try:
                app_maker_obj = AppMaker.objects.get(
                    id=app_id,
                    project_id=project_id,
                    task_template__id=template_id,
                    is_deleted=False)
            except AppMaker.DoesNotExist:
                return False, _("保存失败,当前操作的轻应用不存在或已删除!")

            subject = Subject("user", app_params["username"])
            action = Action(IAMMeta.MINI_APP_EDIT_ACTION)
            resources = res_factory.resources_for_mini_app_obj(app_maker_obj)

            allow_or_raise_auth_failed(iam=iam,
                                       system=IAMMeta.SYSTEM_ID,
                                       subject=subject,
                                       action=action,
                                       resources=resources)

            app_code = app_maker_obj.code
            creator = app_maker_obj.creator
            # app_params["link_prefix"]: current_host.com/appmaker, link_prefix: current_host.com/
            link_prefix = app_params["link_prefix"][:app_params["link_prefix"].
                                                    rfind("appmaker")]
            # app_maker_obj.link: old_host.com/appmaker/xxx, link_suffix: appmaker/xxx
            link_suffix = app_maker_obj.link[app_maker_obj.link.
                                             rfind("appmaker"):]
            # 只保留app_maker_obj.link的后缀,使用环境当前域名作为前缀
            app_link = f"{link_prefix}{link_suffix}"
            app_maker_obj.link = app_link

            if not fake:
                # edit app on blueking
                app_edit_result = edit_maker_app(
                    creator,
                    app_code,
                    app_params["name"],
                    app_link,
                    creator,
                    app_params.get("category") or task_template.category,
                    app_params["desc"],
                )
                if not app_edit_result["result"]:
                    return False, _("编辑轻应用失败:%s") % app_edit_result["message"]

            app_maker_obj.name = app_params["name"]
            app_maker_obj.desc = app_params["desc"]
            app_maker_obj.editor = app_params["username"]
            if "category" in app_params:
                app_maker_obj.category = app_params["category"]
            if "template_scheme_id" in app_params:
                app_maker_obj.template_scheme_id = app_params[
                    "template_scheme_id"]

        # upload app logo
        if not fake and app_params["logo_content"]:
            logo = base64.b64encode(app_params["logo_content"])
            app_logo_result = modify_app_logo(app_maker_obj.creator, app_code,
                                              logo)
            if not app_logo_result["result"]:
                logger.error("AppMaker[id=%s] upload logo failed: %s" %
                             (app_maker_obj.id, app_logo_result["message"]))
            # update app maker info
            app_maker_obj.logo_url = get_app_logo_url(app_code=app_code)

        app_maker_obj.save()
        return True, app_maker_obj
Exemple #6
0
    def obj_create(self, bundle, **kwargs):
        try:
            template_id = bundle.data.pop("template_id")
            template_source = bundle.data.get("template_source", PROJECT)
            name = bundle.data.pop("name")
            cron = bundle.data.pop("cron")
            pipeline_tree = json.loads(bundle.data.pop("pipeline_tree"))
        except (KeyError, ValueError) as e:
            message = "create periodic_task params error: %s" % e.message
            logger.error(message)
            raise BadRequest(message)

        if not isinstance(cron, dict):
            raise BadRequest("cron must be a object json string")

        try:
            project = ProjectResource().get_via_uri(bundle.data.get("project"),
                                                    request=bundle.request)
        except NotFound:
            raise BadRequest("project [uri=%s] does not exist" %
                             bundle.data.get("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:
            raise BadRequest("Periodic task number reaches limit: {}".format(
                periodic_task_limit))

        if template_source == PROJECT:
            try:
                template = TaskTemplate.objects.get(id=template_id,
                                                    project=project,
                                                    is_deleted=False)
            except TaskTemplate.DoesNotExist:
                raise BadRequest(
                    "template[id={template_id}] of project[{project_id}] does not exist"
                    .format(template_id=template_id, project_id=project.id))

            allow_or_raise_immediate_response(
                iam=iam,
                system=IAMMeta.SYSTEM_ID,
                subject=Subject("user", bundle.request.user.username),
                action=Action(IAMMeta.FLOW_CREATE_PERIODIC_TASK_ACTION),
                resources=res_factory.resources_for_flow_obj(template),
            )

            try:
                replace_template_id(TaskTemplate, pipeline_tree)
            except TaskTemplate.DoesNotExist:
                raise BadRequest(
                    "invalid subprocess, check subprocess node please")

        elif template_source == COMMON:
            try:
                template = CommonTemplate.objects.get(id=template_id,
                                                      is_deleted=False)
            except CommonTemplate.DoesNotExist:
                raise BadRequest("common template[id=%s] does not exist" %
                                 template_id)

            allow_or_raise_immediate_response(
                iam=iam,
                system=IAMMeta.SYSTEM_ID,
                subject=Subject("user", bundle.request.user.username),
                action=Action(IAMMeta.COMMON_FLOW_CREATE_PERIODIC_TASK_ACTION),
                resources=[
                    res_factory.resources_for_project_obj(project)[0],
                    res_factory.resources_for_common_flow_obj(template)[0],
                ],
            )

            try:
                replace_template_id(CommonTemplate, pipeline_tree)
            except TaskTemplate.DoesNotExist:
                raise BadRequest(
                    "invalid subprocess, check subprocess node please")

        else:
            raise BadRequest("invalid template_source[%s]" % template_source)

        # XSS handle
        name = standardize_name(name, PERIOD_TASK_NAME_MAX_LENGTH)
        creator = bundle.request.user.username

        # validate pipeline tree
        try:
            validate_web_pipeline_tree(pipeline_tree)
        except PipelineException as e:
            raise BadRequest(str(e))

        kwargs["template_id"] = template_id
        kwargs["template_source"] = template_source
        try:
            kwargs["task"] = PeriodicTask.objects.create_pipeline_task(
                project=project,
                template=template,
                name=name,
                cron=cron,
                pipeline_tree=pipeline_tree,
                creator=creator,
                template_source=template_source,
            )
        except Exception as e:
            logger.warning(traceback.format_exc())
            raise BadRequest(str(e))

        response = super(PeriodicTaskResource,
                         self).obj_create(bundle, **kwargs)
        response.obj.set_enabled(True)

        return response
Exemple #7
0
    def create_pipeline(
        self,
        name: str,
        creator: str,
        pipeline_tree: dict,
        description: str = "",
    ) -> dict:
        """
        创建 pipeline 层模板

        :param name: 模板名
        :type name: str
        :param creator: 创建者
        :type creator: str
        :param pipeline_tree: 模板数据
        :type pipeline_tree: dict
        :param description: 模板描述, defaults to ""
        :type description: str, optional
        :return: [description]
        :rtype: dict
        """
        name = standardize_name(name, TEMPLATE_NODE_NAME_MAX_LENGTH)
        standardize_pipeline_node_name(pipeline_tree)

        try:
            validate_web_pipeline_tree(pipeline_tree)
        except PipelineException as e:
            return {
                "result":
                False,
                "data":
                None,
                "message":
                "[TemplateManager]validate_web_pipeline_tree failed: {}".
                format(str(e)),
                "verbose_message":
                "[TemplateManager]validate_web_pipeline_tree failed: {}".
                format(traceback.format_exc()),
            }

        create_template_kwargs = {
            "name": name,
            "creator": creator,
            "pipeline_tree": pipeline_tree,
            "description": description,
        }
        try:
            pipeline_template = self.template_model_cls.objects.create_pipeline_template(
                **create_template_kwargs)
        except Exception as e:
            return {
                "result":
                False,
                "data":
                None,
                "message":
                "[TemplateManager]create_pipeline_template({kwargs}) failed: {e}"
                .format(kwargs=create_template_kwargs, e=str(e)),
                "verbose_message":
                "[TemplateManager]create_pipeline_template({kwargs}) failed: {trace}"
                .format(kwargs=create_template_kwargs,
                        trace=traceback.format_exc()),
            }

        return {
            "result": True,
            "data": pipeline_template,
            "message": "success",
            "verbose_message": "success"
        }
Exemple #8
0
    def update_pipeline(
        self,
        pipeline_template: PipelineTemplate,
        editor: str,
        name: str = "",
        pipeline_tree: str = None,
        description: str = "",
    ) -> dict:
        """
        更新 pipeline 层模板

        :param pipeline_template: pipeline 模板对象
        :type pipeline_template: PipelineTemplate
        :param editor: 编辑者
        :type editor: str
        :param name: 模板名, defaults to ""
        :type name: str, optional
        :param pipeline_tree: 模板结构, defaults to None
        :type pipeline_tree: str, optional
        :param description: 模板描述, defaults to ""
        :type description: str, optional
        :return: [description]
        :rtype: dict
        """
        update_kwargs = {"editor": editor}
        if name:
            update_kwargs["name"] = standardize_name(
                name, TEMPLATE_NODE_NAME_MAX_LENGTH)

        if description:
            update_kwargs["description"] = description

        if pipeline_tree:
            standardize_pipeline_node_name(pipeline_tree)
            try:
                validate_web_pipeline_tree(pipeline_tree)
            except PipelineException as e:
                return {
                    "result":
                    False,
                    "data":
                    None,
                    "message":
                    "[TemplateManager]validate_web_pipeline_tree failed: {}".
                    format(str(e)),
                    "verbose_message":
                    "[TemplateManager]validate_web_pipeline_tree failed: {}".
                    format(traceback.format_exc()),
                }

            replace_template_id(self.template_model_cls, pipeline_tree)

            pipeline_web_tree = PipelineWebTreeCleaner(pipeline_tree)
            pipeline_web_tree.clean()
            update_kwargs["structure_data"] = pipeline_tree

            try:
                pipeline_template.update_template(**update_kwargs)
            except Exception as e:
                return {
                    "result":
                    False,
                    "data":
                    None,
                    "message":
                    "[TemplateManager]update_template({update_kwargs}) failed: {e}"
                    .format(update_kwargs=update_kwargs, e=str(e)),
                    "verbose_message":
                    "[TemplateManager]update_template({update_kwargs}) failed: {trace}"
                    .format(update_kwargs=update_kwargs,
                            trace=traceback.format_exc()),
                }

            # create node in template
            NodeInTemplate.objects.update_nodes_in_template(
                pipeline_template, pipeline_web_tree.origin_data)
        else:
            for k, v in update_kwargs.items():
                setattr(pipeline_template, k, v)
            pipeline_template.save()

        return {
            "result": True,
            "data": pipeline_template,
            "message": "success",
            "verbose_message": "success"
        }