From 2ab28e4220ffaf790d592953047e5d77b158947c Mon Sep 17 00:00:00 2001 From: guohelu <19503896967@163.com> Date: Mon, 16 Dec 2024 16:46:15 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E6=B5=81=E7=A8=8B=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BC=98=E5=8C=96=20#7626?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/default.py | 4 ++ env.py | 4 ++ gcloud/contrib/template_market/clients.py | 5 +++ gcloud/contrib/template_market/serializers.py | 33 +++++++++++++-- gcloud/contrib/template_market/urls.py | 4 +- gcloud/contrib/template_market/viewsets.py | 40 ++++++++++--------- gcloud/core/context_processors.py | 3 ++ 7 files changed, 69 insertions(+), 24 deletions(-) diff --git a/config/default.py b/config/default.py index be7bbd0ad..e8dbb5a5c 100644 --- a/config/default.py +++ b/config/default.py @@ -890,3 +890,7 @@ def check_engine_admin_permission(request, *args, **kwargs): ENABLE_TEMPLATE_MARKET = env.ENABLE_TEMPLATE_MARKET # 流程商店 API 地址 TEMPLATE_MARKET_API_URL = env.TEMPLATE_MARKET_API_URL +# SRE商店路由 +SRE_STORE_API_URL = env.SRE_STORE_API_URL +# SRE商店帮助文档路由 +SRE_HELP_DOCUMENT_URL = env.SRE_HELP_DOCUMENT_URL diff --git a/env.py b/env.py index 2a4e1546e..18ffc706f 100644 --- a/env.py +++ b/env.py @@ -158,3 +158,7 @@ ENABLE_TEMPLATE_MARKET = False if os.getenv("ENABLE_TEMPLATE_MARKET") is None else True # 流程商店 API 地址 TEMPLATE_MARKET_API_URL = os.getenv("TEMPLATE_MARKET_API_URL", "") +# SRE商店路由 +SRE_STORE_API_URL = os.getenv("SRE_STORE_API_URL", "") +# SRE商店帮助文档路由 +SRE_HELP_DOCUMENT_URL = os.getenv("SRE_HELP_DOCUMENT_URL", "") diff --git a/gcloud/contrib/template_market/clients.py b/gcloud/contrib/template_market/clients.py index fe1114806..2a1fe0f88 100644 --- a/gcloud/contrib/template_market/clients.py +++ b/gcloud/contrib/template_market/clients.py @@ -33,6 +33,11 @@ def get_scene_label(self): response = requests.get(url) return response.json() + def get_risk_level(self, request): + url = self._get_url("/sre_scene/risk_level/") + response = requests.get(url) + return response.json() + def get_template_scene_detail(self, market_record_id): url = self._get_url(f"/sre_scene/flow_template_scene/{market_record_id}/") response = requests.get(url) diff --git a/gcloud/contrib/template_market/serializers.py b/gcloud/contrib/template_market/serializers.py index 89be644f1..aca03dbc9 100644 --- a/gcloud/contrib/template_market/serializers.py +++ b/gcloud/contrib/template_market/serializers.py @@ -14,6 +14,12 @@ from rest_framework import serializers +from gcloud.taskflow3.models import TaskTemplate +from pipeline.models import PipelineTemplate +from pipeline_web.constants import PWE + +TEMPLATE_OPERATE_MAX_NUMBER = 10 + class TemplatePreviewSerializer(serializers.Serializer): name = serializers.CharField(read_only=True, help_text="模板名称") @@ -30,10 +36,8 @@ class TemplateProjectBaseSerializer(serializers.Serializer): class TemplateSharedRecordSerializer(serializers.Serializer): - project_id = serializers.CharField(required=True, max_length=32, help_text="项目id") + project_code = serializers.CharField(required=True, max_length=32, help_text="项目id") template_ids = serializers.ListField(required=True, help_text="关联的模板列表") - creator = serializers.CharField(required=True, max_length=32, help_text="创建者") - extra_info = serializers.JSONField(required=False, allow_null=True, help_text="额外信息") name = serializers.CharField(required=True, help_text="共享名称") code = serializers.CharField(required=True, help_text="共享标识") category = serializers.CharField(required=True, help_text="共享分类") @@ -41,3 +45,26 @@ class TemplateSharedRecordSerializer(serializers.Serializer): usage_id = serializers.IntegerField(required=True, help_text="使用说明id") labels = serializers.ListField(child=serializers.IntegerField(), required=True, help_text="共享标签列表") usage_content = serializers.JSONField(required=True, help_text="使用说明") + + def validate_template_ids(self, value): + if self.check_template_process_count_threshold(value): + raise serializers.ValidationError("The number of processes in the selected template exceeds the limit.") + return value + + def check_template_process_count_threshold(self, template_id_list): + templates = list( + TaskTemplate.objects.filter(id__in=template_id_list).select_related("pipeline_template").values() + ) + pipeline_template_id_list = [tmpl["pipeline_template_id"] for tmpl in templates] + template_objs = PipelineTemplate.objects.filter(template_id__in=pipeline_template_id_list).select_related( + "snapshot" + ) + + count = sum( + 1 + for template_obj in template_objs + for act_id, act in template_obj.data.get(PWE.activities, {}).items() + if act[PWE.type] == PWE.SubProcess + ) + + return len(template_id_list) + count > TEMPLATE_OPERATE_MAX_NUMBER diff --git a/gcloud/contrib/template_market/urls.py b/gcloud/contrib/template_market/urls.py index a85a34312..cc3592424 100644 --- a/gcloud/contrib/template_market/urls.py +++ b/gcloud/contrib/template_market/urls.py @@ -13,11 +13,11 @@ from django.conf.urls import include, url from rest_framework.routers import DefaultRouter -from gcloud.contrib.template_market.viewsets import TemplatePreviewAPIView, SharedTemplateRecordsViewSet +from gcloud.contrib.template_market.viewsets import TemplatePreviewAPIView, TemplateSceneViewSet template_market_router = DefaultRouter() -template_market_router.register(r"shared_templates_records", SharedTemplateRecordsViewSet) +template_market_router.register(r"templates_scene", TemplateSceneViewSet) urlpatterns = [ url(r"^api/", include(template_market_router.urls)), diff --git a/gcloud/contrib/template_market/viewsets.py b/gcloud/contrib/template_market/viewsets.py index 3d07ff172..4c85b5b86 100644 --- a/gcloud/contrib/template_market/viewsets.py +++ b/gcloud/contrib/template_market/viewsets.py @@ -51,7 +51,7 @@ def get(self, request, *args, **kwargs): return Response({"result": True, "data": serializer.data, "code": err_code.SUCCESS.code}) -class SharedTemplateRecordsViewSet(viewsets.ViewSet): +class TemplateSceneViewSet(viewsets.ViewSet): queryset = TemplateSharedRecord.objects.all() serializer_class = TemplateSharedRecordSerializer permission_classes = [permissions.IsAuthenticated, SharedTemplateRecordPermission] @@ -61,18 +61,7 @@ class SharedTemplateRecordsViewSet(viewsets.ViewSet): def _build_template_data(self, serializer, **kwargs): templates = TaskTemplate.objects.filter(id__in=serializer.validated_data["template_ids"], is_deleted=False) template_info = [{"id": template.id, "name": template.name} for template in templates] - data = { - "name": serializer.validated_data["name"], - "code": serializer.validated_data["code"], - "category": serializer.validated_data["category"], - "risk_level": serializer.validated_data["risk_level"], - "usage_id": serializer.validated_data["usage_id"], - "labels": serializer.validated_data["labels"], - "source_system": settings.APP_CODE, - "project_code": serializer.validated_data["project_id"], - "templates": json.dumps(template_info), - "usage_content": serializer.validated_data["usage_content"], - } + data = {"source_system": settings.APP_CODE, "templates": json.dumps(template_info), **serializer.validated_data} market_record_id = kwargs.get("market_record_id") if market_record_id: data["id"] = market_record_id @@ -95,7 +84,6 @@ def get_service_category(self, request, *args, **kwargs): @action(detail=False, methods=["get"]) def get_scene_label(self, request, *args, **kwargs): response_data = self.market_client.get_scene_label() - if not response_data["result"]: logging.exception("Failed to obtain scene tag list") return Response( @@ -107,9 +95,22 @@ def get_scene_label(self, request, *args, **kwargs): ) return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) + @action(detail=False, methods=["get"]) + def get_risk_level(self, request, *args, **kwargs): + response_data = self.market_client.get_risk_level(request) + if not response_data["result"]: + logging.exception("Failed to obtain the market risk level list") + return Response( + { + "result": False, + "message": "Failed to obtain the market risk level list", + "code": err_code.OPERATION_FAIL.code, + } + ) + return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) + def list(self, request, *args, **kwargs): response_data = self.market_client.get_template_scene_list() - if not response_data["result"]: logging.exception("Failed to obtain the market template list") return Response( @@ -137,10 +138,10 @@ def create(self, request, *args, **kwargs): } ) TemplateSharedRecord.objects.update_shared_record( - project_id=int(serializer.validated_data["project_id"]), + project_id=int(serializer.validated_data["project_code"]), new_template_ids=serializer.validated_data["template_ids"], market_record_id=response_data["data"]["id"], - creator=serializer.validated_data["creator"], + creator=request.user.username, ) return Response({"result": True, "data": response_data, "code": err_code.SUCCESS.code}) @@ -149,6 +150,7 @@ def partial_update(self, request, *args, **kwargs): market_record_id = kwargs["pk"] serializer = self.serializer_class(data=request.data, partial=True) serializer.is_valid(raise_exception=True) + existing_records = self.market_client.get_template_scene_detail(market_record_id) existing_market_template_ids = set( [template["id"] for template in json.loads(existing_records["data"]["templates"])] @@ -164,10 +166,10 @@ def partial_update(self, request, *args, **kwargs): } ) TemplateSharedRecord.objects.update_shared_record( - project_id=int(serializer.validated_data["project_id"]), + project_id=int(serializer.validated_data["project_code"]), new_template_ids=serializer.validated_data["template_ids"], market_record_id=market_record_id, - creator=serializer.validated_data["creator"], + creator=request.user.username, existing_market_template_ids=existing_market_template_ids, ) return Response({"result": True, "data": response_data, "code": err_code.SUCCESS.code}) diff --git a/gcloud/core/context_processors.py b/gcloud/core/context_processors.py index 150348155..8030c1194 100644 --- a/gcloud/core/context_processors.py +++ b/gcloud/core/context_processors.py @@ -96,6 +96,9 @@ def mysetting(request): "RUN_VER_NAME": EnvironmentVariables.objects.get_var(run_ver_key, settings.RUN_VER_NAME), "REMOTE_ANALYSIS_URL": settings.REMOTE_ANALYSIS_URL, "REMOTE_API_URL": settings.REMOTE_API_URL, + "ENABLE_TEMPLATE_MARKET": settings.ENABLE_TEMPLATE_MARKET, + "SRE_STORE_API_URL": settings.SRE_STORE_API_URL, + "SRE_HELP_DOCUMENT_URL": settings.SRE_HELP_DOCUMENT_URL, "USERNAME": request.user.username, # 'NICK': request.session.get('nick', ''), # 用户昵称 "NICK": request.user.username, # 用户昵称 From 5602c8e18ecefc54c4e42be39232d0899b0df9a6 Mon Sep 17 00:00:00 2001 From: guohelu <19503896967@163.com> Date: Mon, 16 Dec 2024 20:22:01 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E5=BA=A6=E4=BC=98=E5=8C=96=20#7626?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/default.py | 8 +- env.py | 8 +- gcloud/contrib/template_market/clients.py | 24 +++--- .../migrations/0001_initial.py | 4 +- gcloud/contrib/template_market/models.py | 2 + gcloud/contrib/template_market/viewsets.py | 81 +++++++------------ gcloud/core/context_processors.py | 4 +- 7 files changed, 61 insertions(+), 70 deletions(-) diff --git a/config/default.py b/config/default.py index e8dbb5a5c..df6f1aab0 100644 --- a/config/default.py +++ b/config/default.py @@ -890,7 +890,7 @@ def check_engine_admin_permission(request, *args, **kwargs): ENABLE_TEMPLATE_MARKET = env.ENABLE_TEMPLATE_MARKET # 流程商店 API 地址 TEMPLATE_MARKET_API_URL = env.TEMPLATE_MARKET_API_URL -# SRE商店路由 -SRE_STORE_API_URL = env.SRE_STORE_API_URL -# SRE商店帮助文档路由 -SRE_HELP_DOCUMENT_URL = env.SRE_HELP_DOCUMENT_URL +# 模板市场路由 +TEMPLATE_MARKET_HOST = env.TEMPLATE_MARKET_HOST +# 模板市场文档路由 +TEMPLATE_MARKET_DOC_URL = env.TEMPLATE_MARKET_DOC_URL diff --git a/env.py b/env.py index 18ffc706f..b0bb44774 100644 --- a/env.py +++ b/env.py @@ -158,7 +158,7 @@ ENABLE_TEMPLATE_MARKET = False if os.getenv("ENABLE_TEMPLATE_MARKET") is None else True # 流程商店 API 地址 TEMPLATE_MARKET_API_URL = os.getenv("TEMPLATE_MARKET_API_URL", "") -# SRE商店路由 -SRE_STORE_API_URL = os.getenv("SRE_STORE_API_URL", "") -# SRE商店帮助文档路由 -SRE_HELP_DOCUMENT_URL = os.getenv("SRE_HELP_DOCUMENT_URL", "") +# 模板市场路由 +TEMPLATE_MARKET_HOST = os.getenv("TEMPLATE_MARKET_HOST", "") +# 模板市场文档路由 +TEMPLATE_MARKET_DOC_URL = os.getenv("TEMPLATE_MARKET_DOC_URL", "") diff --git a/gcloud/contrib/template_market/clients.py b/gcloud/contrib/template_market/clients.py index 2a1fe0f88..68b1d3442 100644 --- a/gcloud/contrib/template_market/clients.py +++ b/gcloud/contrib/template_market/clients.py @@ -10,7 +10,7 @@ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ - +import json import requests from gcloud.conf import settings @@ -19,41 +19,47 @@ class MarketAPIClient: def __init__(self): self.base_url = settings.TEMPLATE_MARKET_API_URL + self.headers = { + "X-Bkapi-Authorization": json.dumps( + {"bk_app_code": settings.APP_CODE, "bk_app_secret": settings.SECRET_KEY} + ), + "Content-Type": "application/json", + } def _get_url(self, endpoint): return f"{self.base_url}{endpoint}" def get_service_category(self): url = self._get_url("/category/get_service_category/") - response = requests.get(url) + response = requests.get(url, headers=self.headers) return response.json() def get_scene_label(self): url = self._get_url("/sre_property/scene_label/") - response = requests.get(url) + response = requests.get(url, headers=self.headers) return response.json() - def get_risk_level(self, request): + def get_risk_level(self): url = self._get_url("/sre_scene/risk_level/") - response = requests.get(url) + response = requests.get(url, headers=self.headers) return response.json() def get_template_scene_detail(self, market_record_id): url = self._get_url(f"/sre_scene/flow_template_scene/{market_record_id}/") - response = requests.get(url) + response = requests.get(url, headers=self.headers) return response.json() def get_template_scene_list(self): url = self._get_url("/sre_scene/flow_template_scene/?is_all=true") - response = requests.get(url) + response = requests.get(url, headers=self.headers) return response.json() def create_template_scene(self, data): url = self._get_url("/sre_scene/flow_template_scene/") - response = requests.post(url, json=data) + response = requests.post(url, json=data, headers=self.headers) return response.json() def patch_template_scene(self, data, market_record_id): url = self._get_url(f"/sre_scene/flow_template_scene/{market_record_id}/") - response = requests.patch(url, json=data) + response = requests.patch(url, json=data, headers=self.headers) return response.json() diff --git a/gcloud/contrib/template_market/migrations/0001_initial.py b/gcloud/contrib/template_market/migrations/0001_initial.py index edf2dcb1c..92421809e 100644 --- a/gcloud/contrib/template_market/migrations/0001_initial.py +++ b/gcloud/contrib/template_market/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.15 on 2024-12-13 10:48 +# Generated by Django 3.2.15 on 2024-12-16 11:45 from django.db import migrations, models @@ -17,6 +17,8 @@ class Migration(migrations.Migration): ("project_id", models.IntegerField(default=-1, help_text="项目 ID", verbose_name="项目 ID")), ("template_id", models.IntegerField(db_index=True, help_text="模板 ID", verbose_name="模板 ID")), ("creator", models.CharField(default="", max_length=32, verbose_name="创建者")), + ("create_at", models.DateTimeField(auto_now_add=True, verbose_name="创建时间")), + ("update_at", models.DateTimeField(auto_now=True, verbose_name="更新时间")), ("extra_info", models.JSONField(blank=True, null=True, verbose_name="额外信息")), ], options={ diff --git a/gcloud/contrib/template_market/models.py b/gcloud/contrib/template_market/models.py index f70c58439..229616f31 100644 --- a/gcloud/contrib/template_market/models.py +++ b/gcloud/contrib/template_market/models.py @@ -84,6 +84,8 @@ class TemplateSharedRecord(models.Model): project_id = models.IntegerField(_("项目 ID"), default=-1, help_text="项目 ID") template_id = models.IntegerField(_("模板 ID"), help_text="模板 ID", db_index=True) creator = models.CharField(_("创建者"), max_length=32, default="") + create_at = models.DateTimeField(verbose_name=_("创建时间"), auto_now_add=True) + update_at = models.DateTimeField(verbose_name=_("更新时间"), auto_now=True) extra_info = models.JSONField(_("额外信息"), blank=True, null=True) objects = TemplateSharedManager() diff --git a/gcloud/contrib/template_market/viewsets.py b/gcloud/contrib/template_market/viewsets.py index 4c85b5b86..da6463ecf 100644 --- a/gcloud/contrib/template_market/viewsets.py +++ b/gcloud/contrib/template_market/viewsets.py @@ -67,59 +67,47 @@ def _build_template_data(self, serializer, **kwargs): data["id"] = market_record_id return data - @action(detail=False, methods=["get"]) - def get_service_category(self, request, *args, **kwargs): - response_data = self.market_client.get_service_category() - if not response_data["result"]: - logging.warning("Failed to obtain the market service category") + def _handle_response(self, response_data, error_message): + if not response_data.get("result"): + logging.exception(error_message) return Response( { "result": False, - "message": "Failed to obtain the market service category", + "message": error_message, "code": err_code.OPERATION_FAIL.code, } ) + return None + + @action(detail=False, methods=["get"]) + def get_service_category(self, request, *args, **kwargs): + response_data = self.market_client.get_service_category() + error_response = self._handle_response(response_data, "Failed to obtain scene category") + if error_response: + return error_response return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) @action(detail=False, methods=["get"]) def get_scene_label(self, request, *args, **kwargs): response_data = self.market_client.get_scene_label() - if not response_data["result"]: - logging.exception("Failed to obtain scene tag list") - return Response( - { - "result": False, - "message": "Failed to obtain scene tag list", - "code": err_code.OPERATION_FAIL.code, - } - ) + error_response = self._handle_response(response_data, "Failed to obtain scene tag list") + if error_response: + return error_response return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) @action(detail=False, methods=["get"]) def get_risk_level(self, request, *args, **kwargs): - response_data = self.market_client.get_risk_level(request) - if not response_data["result"]: - logging.exception("Failed to obtain the market risk level list") - return Response( - { - "result": False, - "message": "Failed to obtain the market risk level list", - "code": err_code.OPERATION_FAIL.code, - } - ) + response_data = self.market_client.get_risk_level() + error_response = self._handle_response(response_data, "Failed to obtain the market risk level list") + if error_response: + return error_response return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) def list(self, request, *args, **kwargs): response_data = self.market_client.get_template_scene_list() - if not response_data["result"]: - logging.exception("Failed to obtain the market template list") - return Response( - { - "result": False, - "message": "Failed to obtain the market template list", - "code": err_code.OPERATION_FAIL.code, - } - ) + error_response = self._handle_response(response_data, "Failed to obtain the market template list") + if error_response: + return error_response return Response({"result": True, "data": response_data, "code": err_code.SUCCESS.code}) @swagger_auto_schema(request_body=TemplateSharedRecordSerializer) @@ -129,14 +117,10 @@ def create(self, request, *args, **kwargs): data = self._build_template_data(serializer) response_data = self.market_client.create_template_scene(data) - if not response_data.get("result"): - return Response( - { - "result": False, - "message": "Failed to create market template record", - "code": err_code.OPERATION_FAIL.code, - } - ) + error_response = self._handle_response(response_data, "Failed to create market template record") + if error_response: + return error_response + TemplateSharedRecord.objects.update_shared_record( project_id=int(serializer.validated_data["project_code"]), new_template_ids=serializer.validated_data["template_ids"], @@ -155,16 +139,13 @@ def partial_update(self, request, *args, **kwargs): existing_market_template_ids = set( [template["id"] for template in json.loads(existing_records["data"]["templates"])] ) + data = self._build_template_data(serializer, market_record_id=market_record_id) response_data = self.market_client.patch_template_scene(data, market_record_id) - if not response_data.get("result"): - return Response( - { - "result": False, - "message": "Failed to update market template record", - "code": err_code.OPERATION_FAIL.code, - } - ) + error_response = self._handle_response(response_data, "Failed to update market template record") + if error_response: + return error_response + TemplateSharedRecord.objects.update_shared_record( project_id=int(serializer.validated_data["project_code"]), new_template_ids=serializer.validated_data["template_ids"], diff --git a/gcloud/core/context_processors.py b/gcloud/core/context_processors.py index 8030c1194..8d23cefcf 100644 --- a/gcloud/core/context_processors.py +++ b/gcloud/core/context_processors.py @@ -97,8 +97,8 @@ def mysetting(request): "REMOTE_ANALYSIS_URL": settings.REMOTE_ANALYSIS_URL, "REMOTE_API_URL": settings.REMOTE_API_URL, "ENABLE_TEMPLATE_MARKET": settings.ENABLE_TEMPLATE_MARKET, - "SRE_STORE_API_URL": settings.SRE_STORE_API_URL, - "SRE_HELP_DOCUMENT_URL": settings.SRE_HELP_DOCUMENT_URL, + "TEMPLATE_MARKET_HOST": settings.TEMPLATE_MARKET_HOST, + "TEMPLATE_MARKET_DOC_URL": settings.TEMPLATE_MARKET_DOC_URL, "USERNAME": request.user.username, # 'NICK': request.session.get('nick', ''), # 用户昵称 "NICK": request.user.username, # 用户昵称 From 5a9ad5de6bf306b18db382150f1b3c68995db876 Mon Sep 17 00:00:00 2001 From: guohelu <19503896967@163.com> Date: Tue, 17 Dec 2024 14:45:57 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=AE=A1=E6=95=B0?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=20#7626?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gcloud/contrib/template_market/clients.py | 53 +++++++++---------- gcloud/contrib/template_market/serializers.py | 34 +++++------- gcloud/contrib/template_market/viewsets.py | 16 +++--- 3 files changed, 49 insertions(+), 54 deletions(-) diff --git a/gcloud/contrib/template_market/clients.py b/gcloud/contrib/template_market/clients.py index 68b1d3442..d9e2c5ed0 100644 --- a/gcloud/contrib/template_market/clients.py +++ b/gcloud/contrib/template_market/clients.py @@ -29,37 +29,36 @@ def __init__(self): def _get_url(self, endpoint): return f"{self.base_url}{endpoint}" - def get_service_category(self): - url = self._get_url("/category/get_service_category/") - response = requests.get(url, headers=self.headers) - return response.json() + def _make_request(self, method, endpoint, **kwargs): + url = self._get_url(endpoint) - def get_scene_label(self): - url = self._get_url("/sre_property/scene_label/") - response = requests.get(url, headers=self.headers) - return response.json() + headers = {**self.headers} + bk_username = kwargs.get("username") + if bk_username: + headers["bk_username"] = bk_username - def get_risk_level(self): - url = self._get_url("/sre_scene/risk_level/") - response = requests.get(url, headers=self.headers) + response = requests.request(method, url, headers=headers, json=kwargs.get("data")) return response.json() - def get_template_scene_detail(self, market_record_id): - url = self._get_url(f"/sre_scene/flow_template_scene/{market_record_id}/") - response = requests.get(url, headers=self.headers) - return response.json() + def get_service_category(self, username): + return self._make_request("GET", "/category/get_service_category/", username=username) - def get_template_scene_list(self): - url = self._get_url("/sre_scene/flow_template_scene/?is_all=true") - response = requests.get(url, headers=self.headers) - return response.json() + def get_scene_label(self, username): + return self._make_request("GET", "/sre_property/scene_label/", username=username) - def create_template_scene(self, data): - url = self._get_url("/sre_scene/flow_template_scene/") - response = requests.post(url, json=data, headers=self.headers) - return response.json() + def get_risk_level(self, username): + return self._make_request("GET", "/sre_scene/risk_level/", username=username) - def patch_template_scene(self, data, market_record_id): - url = self._get_url(f"/sre_scene/flow_template_scene/{market_record_id}/") - response = requests.patch(url, json=data, headers=self.headers) - return response.json() + def get_template_scene_detail(self, market_record_id, username): + return self._make_request("GET", f"/sre_scene/flow_template_scene/{market_record_id}/", username=username) + + def get_template_scene_list(self, username): + return self._make_request("GET", "/sre_scene/flow_template_scene/?is_all=true", username=username) + + def create_template_scene(self, data, username): + return self._make_request("POST", "/sre_scene/flow_template_scene/", username=username, data=data) + + def patch_template_scene(self, data, market_record_id, username): + return self._make_request( + "PATCH", f"/sre_scene/flow_template_scene/{market_record_id}/", username=username, data=data + ) diff --git a/gcloud/contrib/template_market/serializers.py b/gcloud/contrib/template_market/serializers.py index aca03dbc9..cc29ee690 100644 --- a/gcloud/contrib/template_market/serializers.py +++ b/gcloud/contrib/template_market/serializers.py @@ -15,7 +15,6 @@ from rest_framework import serializers from gcloud.taskflow3.models import TaskTemplate -from pipeline.models import PipelineTemplate from pipeline_web.constants import PWE TEMPLATE_OPERATE_MAX_NUMBER = 10 @@ -42,29 +41,24 @@ class TemplateSharedRecordSerializer(serializers.Serializer): code = serializers.CharField(required=True, help_text="共享标识") category = serializers.CharField(required=True, help_text="共享分类") risk_level = serializers.IntegerField(required=True, help_text="风险级别") - usage_id = serializers.IntegerField(required=True, help_text="使用说明id") + usage_id = serializers.IntegerField(required=False, help_text="使用说明id") labels = serializers.ListField(child=serializers.IntegerField(), required=True, help_text="共享标签列表") usage_content = serializers.JSONField(required=True, help_text="使用说明") def validate_template_ids(self, value): - if self.check_template_process_count_threshold(value): + if not self.check_template_count_threshold(value): raise serializers.ValidationError("The number of processes in the selected template exceeds the limit.") + return value - def check_template_process_count_threshold(self, template_id_list): - templates = list( - TaskTemplate.objects.filter(id__in=template_id_list).select_related("pipeline_template").values() - ) - pipeline_template_id_list = [tmpl["pipeline_template_id"] for tmpl in templates] - template_objs = PipelineTemplate.objects.filter(template_id__in=pipeline_template_id_list).select_related( - "snapshot" - ) - - count = sum( - 1 - for template_obj in template_objs - for act_id, act in template_obj.data.get(PWE.activities, {}).items() - if act[PWE.type] == PWE.SubProcess - ) - - return len(template_id_list) + count > TEMPLATE_OPERATE_MAX_NUMBER + def check_template_count_threshold(self, template_id_list): + if len(template_id_list) > TEMPLATE_OPERATE_MAX_NUMBER: + return False + + templates = TaskTemplate.objects.filter(id__in=template_id_list).select_related("pipeline_template") + + acts = [act for tmpl in templates for act in tmpl.pipeline_template.data.get(PWE.activities, {}).values()] + # TODO: 目前只做了一层的数量统计 + count = sum(act["type"] == PWE.SubProcess for act in acts) + + return len(template_id_list) + count < TEMPLATE_OPERATE_MAX_NUMBER diff --git a/gcloud/contrib/template_market/viewsets.py b/gcloud/contrib/template_market/viewsets.py index da6463ecf..05d2c46b9 100644 --- a/gcloud/contrib/template_market/viewsets.py +++ b/gcloud/contrib/template_market/viewsets.py @@ -81,7 +81,7 @@ def _handle_response(self, response_data, error_message): @action(detail=False, methods=["get"]) def get_service_category(self, request, *args, **kwargs): - response_data = self.market_client.get_service_category() + response_data = self.market_client.get_service_category(username=request.user.username) error_response = self._handle_response(response_data, "Failed to obtain scene category") if error_response: return error_response @@ -89,7 +89,7 @@ def get_service_category(self, request, *args, **kwargs): @action(detail=False, methods=["get"]) def get_scene_label(self, request, *args, **kwargs): - response_data = self.market_client.get_scene_label() + response_data = self.market_client.get_scene_label(username=request.user.username) error_response = self._handle_response(response_data, "Failed to obtain scene tag list") if error_response: return error_response @@ -97,14 +97,14 @@ def get_scene_label(self, request, *args, **kwargs): @action(detail=False, methods=["get"]) def get_risk_level(self, request, *args, **kwargs): - response_data = self.market_client.get_risk_level() + response_data = self.market_client.get_risk_level(username=request.user.username) error_response = self._handle_response(response_data, "Failed to obtain the market risk level list") if error_response: return error_response return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) def list(self, request, *args, **kwargs): - response_data = self.market_client.get_template_scene_list() + response_data = self.market_client.get_template_scene_list(username=request.user.username) error_response = self._handle_response(response_data, "Failed to obtain the market template list") if error_response: return error_response @@ -116,7 +116,7 @@ def create(self, request, *args, **kwargs): serializer.is_valid(raise_exception=True) data = self._build_template_data(serializer) - response_data = self.market_client.create_template_scene(data) + response_data = self.market_client.create_template_scene(data, username=request.user.username) error_response = self._handle_response(response_data, "Failed to create market template record") if error_response: return error_response @@ -135,13 +135,15 @@ def partial_update(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, partial=True) serializer.is_valid(raise_exception=True) - existing_records = self.market_client.get_template_scene_detail(market_record_id) + existing_records = self.market_client.get_template_scene_detail( + market_record_id, username=request.user.username + ) existing_market_template_ids = set( [template["id"] for template in json.loads(existing_records["data"]["templates"])] ) data = self._build_template_data(serializer, market_record_id=market_record_id) - response_data = self.market_client.patch_template_scene(data, market_record_id) + response_data = self.market_client.patch_template_scene(data, market_record_id, username=request.user.username) error_response = self._handle_response(response_data, "Failed to update market template record") if error_response: return error_response From b4fe30bf551ad10f74e530e219b66caacee1d1c7 Mon Sep 17 00:00:00 2001 From: guohelu <19503896967@163.com> Date: Tue, 17 Dec 2024 15:46:49 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E5=8C=96=E5=8F=82=E6=95=B0=20#7626?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gcloud/contrib/template_market/clients.py | 42 +++++++++------------- gcloud/contrib/template_market/viewsets.py | 24 +++++++------ 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/gcloud/contrib/template_market/clients.py b/gcloud/contrib/template_market/clients.py index d9e2c5ed0..549ef3287 100644 --- a/gcloud/contrib/template_market/clients.py +++ b/gcloud/contrib/template_market/clients.py @@ -17,11 +17,11 @@ class MarketAPIClient: - def __init__(self): + def __init__(self, username): self.base_url = settings.TEMPLATE_MARKET_API_URL self.headers = { "X-Bkapi-Authorization": json.dumps( - {"bk_app_code": settings.APP_CODE, "bk_app_secret": settings.SECRET_KEY} + {"bk_app_code": settings.APP_CODE, "bk_app_secret": settings.SECRET_KEY, "bk_username": username} ), "Content-Type": "application/json", } @@ -31,34 +31,26 @@ def _get_url(self, endpoint): def _make_request(self, method, endpoint, **kwargs): url = self._get_url(endpoint) - - headers = {**self.headers} - bk_username = kwargs.get("username") - if bk_username: - headers["bk_username"] = bk_username - - response = requests.request(method, url, headers=headers, json=kwargs.get("data")) + response = requests.request(method, url, headers=self.headers, json=kwargs.get("data")) return response.json() - def get_service_category(self, username): - return self._make_request("GET", "/category/get_service_category/", username=username) + def get_service_category(self): + return self._make_request("GET", "/category/get_service_category/") - def get_scene_label(self, username): - return self._make_request("GET", "/sre_property/scene_label/", username=username) + def get_scene_label(self): + return self._make_request("GET", "/sre_property/scene_label/") - def get_risk_level(self, username): - return self._make_request("GET", "/sre_scene/risk_level/", username=username) + def get_risk_level(self): + return self._make_request("GET", "/sre_scene/risk_level/") - def get_template_scene_detail(self, market_record_id, username): - return self._make_request("GET", f"/sre_scene/flow_template_scene/{market_record_id}/", username=username) + def get_template_scene_detail(self, market_record_id): + return self._make_request("GET", f"/sre_scene/flow_template_scene/{market_record_id}/") - def get_template_scene_list(self, username): - return self._make_request("GET", "/sre_scene/flow_template_scene/?is_all=true", username=username) + def get_template_scene_list(self): + return self._make_request("GET", "/sre_scene/flow_template_scene/?is_all=true") - def create_template_scene(self, data, username): - return self._make_request("POST", "/sre_scene/flow_template_scene/", username=username, data=data) + def create_template_scene(self, data): + return self._make_request("POST", "/sre_scene/flow_template_scene/", data=data) - def patch_template_scene(self, data, market_record_id, username): - return self._make_request( - "PATCH", f"/sre_scene/flow_template_scene/{market_record_id}/", username=username, data=data - ) + def patch_template_scene(self, data, market_record_id): + return self._make_request("PATCH", f"/sre_scene/flow_template_scene/{market_record_id}/", data=data) diff --git a/gcloud/contrib/template_market/viewsets.py b/gcloud/contrib/template_market/viewsets.py index 05d2c46b9..2cdcdfc04 100644 --- a/gcloud/contrib/template_market/viewsets.py +++ b/gcloud/contrib/template_market/viewsets.py @@ -56,7 +56,7 @@ class TemplateSceneViewSet(viewsets.ViewSet): serializer_class = TemplateSharedRecordSerializer permission_classes = [permissions.IsAuthenticated, SharedTemplateRecordPermission] - market_client = MarketAPIClient() + market_client = MarketAPIClient def _build_template_data(self, serializer, **kwargs): templates = TaskTemplate.objects.filter(id__in=serializer.validated_data["template_ids"], is_deleted=False) @@ -81,7 +81,8 @@ def _handle_response(self, response_data, error_message): @action(detail=False, methods=["get"]) def get_service_category(self, request, *args, **kwargs): - response_data = self.market_client.get_service_category(username=request.user.username) + client = self.market_client(username=request.user.username) + response_data = client.get_service_category() error_response = self._handle_response(response_data, "Failed to obtain scene category") if error_response: return error_response @@ -89,7 +90,8 @@ def get_service_category(self, request, *args, **kwargs): @action(detail=False, methods=["get"]) def get_scene_label(self, request, *args, **kwargs): - response_data = self.market_client.get_scene_label(username=request.user.username) + client = self.market_client(username=request.user.username) + response_data = client.get_scene_label() error_response = self._handle_response(response_data, "Failed to obtain scene tag list") if error_response: return error_response @@ -97,14 +99,16 @@ def get_scene_label(self, request, *args, **kwargs): @action(detail=False, methods=["get"]) def get_risk_level(self, request, *args, **kwargs): - response_data = self.market_client.get_risk_level(username=request.user.username) + client = self.market_client(username=request.user.username) + response_data = client.get_risk_level() error_response = self._handle_response(response_data, "Failed to obtain the market risk level list") if error_response: return error_response return Response({"result": True, "data": response_data["data"], "code": err_code.SUCCESS.code}) def list(self, request, *args, **kwargs): - response_data = self.market_client.get_template_scene_list(username=request.user.username) + client = self.market_client(username=request.user.username) + response_data = client.get_template_scene_list() error_response = self._handle_response(response_data, "Failed to obtain the market template list") if error_response: return error_response @@ -116,7 +120,8 @@ def create(self, request, *args, **kwargs): serializer.is_valid(raise_exception=True) data = self._build_template_data(serializer) - response_data = self.market_client.create_template_scene(data, username=request.user.username) + client = self.market_client(username=request.user.username) + response_data = client.create_template_scene(data) error_response = self._handle_response(response_data, "Failed to create market template record") if error_response: return error_response @@ -135,15 +140,14 @@ def partial_update(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, partial=True) serializer.is_valid(raise_exception=True) - existing_records = self.market_client.get_template_scene_detail( - market_record_id, username=request.user.username - ) + client = self.market_client(username=request.user.username) + existing_records = client.get_template_scene_detail(market_record_id) existing_market_template_ids = set( [template["id"] for template in json.loads(existing_records["data"]["templates"])] ) data = self._build_template_data(serializer, market_record_id=market_record_id) - response_data = self.market_client.patch_template_scene(data, market_record_id, username=request.user.username) + response_data = client.patch_template_scene(data, market_record_id) error_response = self._handle_response(response_data, "Failed to update market template record") if error_response: return error_response