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)
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 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)
def handle_task_name_attr(data): data["name"] = standardize_name(data["name"], TASK_NAME_MAX_LENGTH) standardize_pipeline_node_name(data["pipeline_tree"])
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
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
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" }
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" }