Skip to content

Commit

Permalink
feat(backend): 标签功能 TencentBlueKing#6235
Browse files Browse the repository at this point in the history
# Reviewed, transaction id: 17937
  • Loading branch information
zhangzhw8 committed Sep 19, 2024
1 parent e57f25a commit f57b569
Show file tree
Hide file tree
Showing 16 changed files with 175 additions and 26 deletions.
15 changes: 13 additions & 2 deletions dbm-ui/backend/db_meta/enums/comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class DBCCModule(str, StructuredEnum):


class TagType(str, StructuredEnum):
CUSTOM = EnumField("custom", _("custom"))
SYSTEM = EnumField("system", _("system"))
CUSTOM = EnumField("custom", _("自定义标签"))
SYSTEM = EnumField("system", _("系统标签"))
BUILTIN = EnumField("builtin", _("内置标签"))


class SystemTagEnum(str, StructuredEnum):
Expand All @@ -36,6 +37,16 @@ class SystemTagEnum(str, StructuredEnum):
TEMPORARY = EnumField("temporary", _("temporary"))


class TagResourceEnum(int, StructuredEnum):
"""资源类型"""

CLUSTER = EnumField(0, _("集群"))
STORAGE_INSTANCE = EnumField(1, _("存储实例"))
PROXY_INSTANCE = EnumField(2, _("代理实例"))
MACHINE = EnumField(3, _("实例机器"))
RESOURCE_MACHINE = EnumField(4, _("资源池机器"))


class RedisVerUpdateNodeType(str, StructuredEnum):
"""redis版本升级节点类型"""

Expand Down
2 changes: 2 additions & 0 deletions dbm-ui/backend/db_meta/models/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
ClusterSqlserverStatusFlags,
)
from backend.db_meta.exceptions import ClusterExclusiveOperateException, DBMetaException
from backend.db_meta.models.tag import Tag
from backend.db_services.version.constants import LATEST, PredixyVersion, TwemproxyVersion
from backend.flow.consts import DEFAULT_RIAK_PORT
from backend.ticket.constants import TicketType
Expand All @@ -68,6 +69,7 @@ class Cluster(AuditedModel):
max_length=128, help_text=_("容灾要求"), choices=AffinityEnum.get_choices(), default=AffinityEnum.NONE.value
)
time_zone = models.CharField(max_length=16, default=DEFAULT_TIME_ZONE, help_text=_("集群所在的时区"))
tags = models.ManyToManyField(Tag, blank=True, help_text=_("标签(外键)"))

class Meta:
unique_together = [("bk_biz_id", "immute_domain", "cluster_type", "db_module_id"), ("immute_domain",)]
Expand Down
21 changes: 14 additions & 7 deletions dbm-ui/backend/db_meta/models/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,27 @@
from django.utils.translation import ugettext_lazy as _

from backend.bk_web.models import AuditedModel
from backend.configuration.constants import PLAT_BIZ_ID
from backend.db_meta.enums.comm import TagType
from backend.db_meta.models import Cluster


class Tag(AuditedModel):
bk_biz_id = models.IntegerField(default=0)
name = models.CharField(max_length=64, default="", help_text=_("tag名称"))
type = models.CharField(max_length=64, help_text=_("tag类型"), choices=TagType.get_choices())
cluster = models.ManyToManyField(Cluster, blank=True, help_text=_("关联集群"))
bk_biz_id = models.IntegerField(help_text=_("业务 ID"), default=0)
key = models.CharField(help_text=_("标签键"), default="", max_length=64)
value = models.CharField(help_text=_("标签值"), default="", max_length=64)
type = models.CharField(help_text=_("tag类型"), max_length=64, choices=TagType.get_choices())

class Meta:
unique_together = ["bk_biz_id", "name"]
unique_together = ["bk_biz_id", "key", "value"]

@property
def tag_desc(self):
"""仅返回tag的信息"""
return {"bk_biz_id": self.bk_biz_id, "name": self.name, "type": self.type}
return {"bk_biz_id": self.bk_biz_id, "key": self.key, "type": self.type}

@classmethod
def get_or_create_system_tag(cls, key: str, value: str):
tag, created = cls.objects.get_or_create(
bk_biz_id=PLAT_BIZ_ID, key=key, value=value, type=TagType.SYSTEM.value
)
return tag
13 changes: 11 additions & 2 deletions dbm-ui/backend/db_services/dbbase/resources/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ def export_instance(cls, bk_biz_id: int, bk_host_ids: list) -> HttpResponse:
@classmethod
def get_temporary_cluster_info(cls, cluster, ticket_type):
"""如果当前集群是临时集群,则补充临时集群相关信息。"""
# TODO 临时关闭 tag
return {}
tags = [tag.name for tag in cluster.tag_set.all()]
if SystemTagEnum.TEMPORARY.value not in tags:
return {}
Expand Down Expand Up @@ -397,8 +399,14 @@ def _list_clusters(
for param in filter_params_map:
if query_params.get(param):
query_filters &= filter_params_map[param]

# 对标签进行过滤,标签“且”查询,需以追加 filter 的方式实现
cluster_queryset = Cluster.objects.filter(query_filters)
for tag_id in query_params.get("tag_ids", "").split(","):
cluster_queryset = cluster_queryset.filter(tags__id=tag_id)

# 一join多的一方会有重复的数据,去重
cluster_queryset = Cluster.objects.filter(query_filters).distinct()
cluster_queryset = cluster_queryset.distinct()

def filter_inst_queryset(_cluster_queryset, _proxy_queryset, _storage_queryset, _filters):
# 注意这里用新的变量获取过滤后的queryset,不要用原queryset过滤,会影响后续集群关联实例的获取
Expand Down Expand Up @@ -472,7 +480,7 @@ def _filter_cluster_hook(
Prefetch("proxyinstance_set", queryset=proxy_queryset.select_related("machine"), to_attr="proxies"),
Prefetch("storageinstance_set", queryset=storage_queryset.select_related("machine"), to_attr="storages"),
Prefetch("clusterentry_set", to_attr="entries"),
"tag_set",
"tags",
)
cluster_ids = list(cluster_queryset.values_list("id", flat=True))

Expand Down Expand Up @@ -564,6 +572,7 @@ def _to_cluster_representation(
"updater": cluster.updater,
"create_at": datetime2str(cluster.create_at),
"update_at": datetime2str(cluster.update_at),
"tags": [{tag.key: tag.value} for tag in cluster.tags.all()],
}

@classmethod
Expand Down
1 change: 1 addition & 0 deletions dbm-ui/backend/db_services/dbbase/resources/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ListResourceSLZ(serializers.Serializer):
db_module_id = serializers.CharField(required=False, help_text=_("所属DB模块"))
bk_cloud_id = serializers.CharField(required=False, help_text=_("管控区域"))
cluster_type = serializers.CharField(required=False, help_text=_("集群类型"))
tag_ids = serializers.CharField(required=False, help_text=_("标签"))


class ListMySQLResourceSLZ(ListResourceSLZ):
Expand Down
2 changes: 1 addition & 1 deletion dbm-ui/backend/db_services/group/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from backend.db_meta.models import Group, GroupInstance


class GroupSerializer(AuditedSerializer, serializers.ModelSerializer):
class TagSerializer(AuditedSerializer, serializers.ModelSerializer):
instance_count = serializers.SerializerMethodField(help_text=_("实例数量"))

class Meta:
Expand Down
12 changes: 6 additions & 6 deletions dbm-ui/backend/db_services/group/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
)
from backend.db_meta.models import Group
from backend.db_services.group.handlers import GroupHandler
from backend.db_services.group.serializers import GroupMoveInstancesSerializer, GroupSerializer
from backend.db_services.group.serializers import GroupMoveInstancesSerializer, TagSerializer
from backend.iam_app.handlers.drf_perm.base import RejectPermission, get_request_key_id

SWAGGER_TAG = _("分组")
Expand All @@ -35,7 +35,7 @@ class GroupViewSet(viewsets.AuditedModelViewSet):
"""

queryset = Group.objects.all()
serializer_class = GroupSerializer
serializer_class = TagSerializer
pagination_class = AuditedLimitOffsetPagination

# TODO: 暂时屏蔽对influxdb的鉴权
Expand Down Expand Up @@ -74,7 +74,7 @@ def get_queryset(self):

@common_swagger_auto_schema(
operation_summary=_("分组详情"),
responses={status.HTTP_200_OK: GroupSerializer(label=_("分组详情"))},
responses={status.HTTP_200_OK: TagSerializer(label=_("分组详情"))},
tags=[SWAGGER_TAG],
)
def retrieve(self, request, *args, **kwargs):
Expand All @@ -98,7 +98,7 @@ def list(self, request, *args, **kwargs):
@common_swagger_auto_schema(
operation_summary=_("创建新分组"),
auto_schema=ResponseSwaggerAutoSchema,
responses={status.HTTP_200_OK: GroupSerializer(label=_("创建新分组"))},
responses={status.HTTP_200_OK: TagSerializer(label=_("创建新分组"))},
tags=[SWAGGER_TAG],
)
def create(self, request, *args, **kwargs):
Expand All @@ -107,7 +107,7 @@ def create(self, request, *args, **kwargs):
@common_swagger_auto_schema(
operation_summary=_("更新分组信息"),
auto_schema=ResponseSwaggerAutoSchema,
responses={status.HTTP_200_OK: GroupSerializer(label=_("更新分组信息"))},
responses={status.HTTP_200_OK: TagSerializer(label=_("更新分组信息"))},
tags=[SWAGGER_TAG],
)
def update(self, request, *args, **kwargs):
Expand All @@ -116,7 +116,7 @@ def update(self, request, *args, **kwargs):
@common_swagger_auto_schema(
operation_summary=_("删除分组"),
auto_schema=ResponseSwaggerAutoSchema,
responses={status.HTTP_200_OK: GroupSerializer(label=_("删除分组"))},
responses={status.HTTP_200_OK: TagSerializer(label=_("删除分组"))},
tags=[SWAGGER_TAG],
)
def destroy(self, request, *args, **kwargs):
Expand Down
10 changes: 10 additions & 0 deletions dbm-ui/backend/db_services/tag/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
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.
"""
42 changes: 42 additions & 0 deletions dbm-ui/backend/db_services/tag/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
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.
"""
from typing import Dict, List


class TagHandler:
"""标签的操作类"""

def batch_set_tags(self, tag_ids: List[int]):
"""
给资源批量设置标签
"""
# 1. 判断标签中 key 是否允许多值

# 2. 批量设置标签
pass

def delete_tags(self, tag_ids: List[int]):
"""
删除标签
"""
# 1. 检查标签是否被引用

# 2. 批量删除标签

def create_tags(self, tags: List[Dict[str, str]]):
"""
批量创建标签
"""

def list_tags(self):
"""
标签列表
"""
20 changes: 20 additions & 0 deletions dbm-ui/backend/db_services/tag/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
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.
"""

from rest_framework import serializers

from backend.bk_web.serializers import AuditedSerializer


class TagSerializer(AuditedSerializer, serializers.ModelSerializer):
"""
标签序列化器
"""
19 changes: 19 additions & 0 deletions dbm-ui/backend/db_services/tag/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
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.
"""

from rest_framework.routers import DefaultRouter

from . import views

routers = DefaultRouter(trailing_slash=True)
routers.register("", views.TagViewSet, basename="tag")

urlpatterns = routers.urls
27 changes: 27 additions & 0 deletions dbm-ui/backend/db_services/tag/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
"""
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at https://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
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.
"""

from django.utils.translation import ugettext as _

from backend.bk_web import viewsets
from backend.db_meta.models import Tag
from backend.db_services.group.serializers import TagSerializer

SWAGGER_TAG = _("标签")


class TagViewSet(viewsets.AuditedModelViewSet):
"""
标签视图
"""

queryset = Tag.objects.all()
serializer_class = TagSerializer
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ def pre_callback(self):

# 对临时集群记录变更
temporary_tag, _ = Tag.objects.get_or_create(
bk_biz_id=self.ticket.bk_biz_id, name=SystemTagEnum.TEMPORARY.value, type=TagType.SYSTEM.value
bk_biz_id=self.ticket.bk_biz_id, key=SystemTagEnum.TEMPORARY.value, value=True, type=TagType.SYSTEM.value
)
target_cluster.tag_set.add(temporary_tag)
target_cluster.tags.add(temporary_tag)
ClusterOperateRecord.objects.get_or_create(
cluster_id=target_cluster.id, ticket=self.ticket, flow=rollback_flow
)
Expand Down
1 change: 1 addition & 0 deletions dbm-ui/backend/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
path("db_dirty/", include("backend.db_dirty.urls")),
path("dbbase/", include("backend.db_services.dbbase.urls")),
path("quick_search/", include("backend.db_services.quick_search.urls")),
path("tag/", include("backend.db_services.tag.urls")),
path("plugin/", include("backend.db_services.plugin.urls")),
]

Expand Down
2 changes: 1 addition & 1 deletion dbm-ui/scripts/ci/code_quality.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ echo "未通过数: $TEST_NOT_SUCCESS_COUNT"

if [[ $TEST_NOT_SUCCESS_COUNT -ne 0 ]];
then
echo -e "$TEST_LOGS"
echo -e "\033[1;31m $TEST_LOGS \033[0m"
exit 1
fi

Expand Down
10 changes: 5 additions & 5 deletions dbm-ui/scripts/ci/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ poetry export --without-hashes -f requirements.txt --output requirements.txt
pip install -r requirements.txt >> /tmp/pip_install.log
if [[ $? -ne 0 ]];
then
echo "Error: pip install -r requirements.txt error!"
echo -e "\033[1;31m Error: pip install -r requirements.txt error! \033[0m"
cat /tmp/pip_install.log
FAILED_COUNT=$[$FAILED_COUNT+1]
fi
Expand Down Expand Up @@ -57,7 +57,7 @@ echo "开始执行 python manage.py migrate --database=report_db"
python manage.py migrate --database=report_db >> /tmp/migrate_report_db.log
if [[ $? -ne 0 ]];
then
echo "Error: python manage.py migrate --database=report_db 执行失败!请检查 migrations 文件"
echo -e "\033[1;31m Error: python manage.py migrate --database=report_db 执行失败!请检查 migrations 文件 \033[0m"
cat /tmp/migrate_report_db.log
FAILED_COUNT=$[$FAILED_COUNT+1]
fi
Expand All @@ -66,7 +66,7 @@ echo "开始执行 python manage.py migrate"
python manage.py migrate >> /tmp/migrate.log
if [[ $? -ne 0 ]];
then
echo "Error: python manage.py migrate 执行失败!请检查 migrations 文件"
echo -e "\033[1;31m Error: python manage.py migrate 执行失败!请检查 migrations 文件 \033[0m"
cat /tmp/migrate.log
FAILED_COUNT=$[$FAILED_COUNT+1]
fi
Expand All @@ -76,13 +76,13 @@ python manage.py createcachetable django_cache
python manage.py language_finder -p backend/ -m error
if [[ $? -ne 0 ]];
then
echo "Error: python manage.py language_finder -p backend/ -m error 执行失败!请检查中文是否已标记"
echo -e "\033[1;31m Error: python manage.py language_finder -p backend/ -m error 执行失败!请检查中文是否已标记 \033[0m"
FAILED_COUNT=$[$FAILED_COUNT+1]
fi

if [[ $FAILED_COUNT -ne 0 ]];
then
echo "Error: 前置命令未通过! 前置命令执行失败数量: $FAILED_COUNT"
echo -e "\033[1;31m Error: 前置命令未通过! 前置命令执行失败数量: $FAILED_COUNT \033[0m"
exit 1
else
echo "前置命令已通过"
Expand Down

0 comments on commit f57b569

Please sign in to comment.