Skip to content

Commit

Permalink
bugfix: 修复在 CMDB 彻底删除业务后标准运维仍可选中的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhuoZhuoCrayon authored and hanshuaikang committed Dec 5, 2023
1 parent 36811b0 commit f2e5467
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 38 deletions.
13 changes: 11 additions & 2 deletions gcloud/core/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from django.db import IntegrityError

from gcloud.conf import settings
from gcloud.core.utils import get_user_business_list
from gcloud.core.models import Business, Project, UserDefaultProject
from gcloud.core.utils import get_user_business_list
from gcloud.iam_auth.utils import get_user_projects

logger = logging.getLogger("root")
Expand All @@ -31,6 +31,7 @@
def sync_projects_from_cmdb(username, use_cache=True):
biz_list = get_user_business_list(username=username, use_cache=use_cache)
business_dict = {}
all_biz_cc_ids = set()
archived_biz_cc_ids = set()
active_biz_cc_ids = set()

Expand All @@ -41,6 +42,8 @@ def sync_projects_from_cmdb(username, use_cache=True):
biz_cc_id = biz["bk_biz_id"]
biz_status = biz.get("bk_data_status", "enable")

all_biz_cc_ids.add(biz_cc_id)

if biz_status == "disabled":
archived_biz_cc_ids.add(biz_cc_id)

Expand Down Expand Up @@ -76,8 +79,14 @@ def sync_projects_from_cmdb(username, use_cache=True):
except IntegrityError as e:
logger.warning("[sync_project_from_cmdb_business] create projects failed due to: {}".format(e))

# 计算出 CC 已删除并且存在于项目中的业务 ID 集合,对这部分项目也需要进行归档
exist_sync_biz_cc_ids = set(Project.objects.filter(from_cmdb=True).values_list("bk_biz_id", flat=True))
deleted_biz_cc_ids = exist_sync_biz_cc_ids - all_biz_cc_ids

# update project's status which sync from cmdb
Project.objects.update_business_project_status(archived_cc_ids=archived_biz_cc_ids, active_cc_ids=active_biz_cc_ids)
Project.objects.update_business_project_status(
archived_cc_ids=archived_biz_cc_ids | deleted_biz_cc_ids, active_cc_ids=active_biz_cc_ids
)


def get_default_project_for_user(username):
Expand Down
95 changes: 59 additions & 36 deletions gcloud/tests/core/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

from gcloud.core import project
from gcloud.core.models import Business, Project

from gcloud.tests.mock import * # noqa
from gcloud.tests.mock_settings import * # noqa

Expand Down Expand Up @@ -64,6 +63,30 @@ def tearDown(self):
Business.objects.all().delete()
Project.objects.all().delete()

@classmethod
def generate_business_update_or_create_params_list(cls, biz_list):
return [
dict(
cc_id=biz["bk_biz_id"],
defaults={
"cc_name": biz["bk_biz_name"],
"cc_owner": biz["bk_supplier_account"],
"cc_company": biz["bk_supplier_id"],
"time_zone": biz["time_zone"],
"life_cycle": biz["life_cycle"],
"status": biz["bk_data_status"],
},
)
for biz in biz_list
]

@classmethod
def generate_business_update_or_create_calls(cls, biz_list):
return [
mock.call(**update_or_create_params)
for update_or_create_params in cls.generate_business_update_or_create_params_list(biz_list)
]

@patch(CORE_PROJECT_GET_USER_BUSINESS_LIST, MagicMock(return_value=[]))
@patch(CORE_MODEL_PROJECT_SYNC_PROJECT, MagicMock(return_value=[]))
@patch(CORE_MODEL_USER_DEFAULT_PROJECT_INIT_USER_DEFAULT_PROJECT, MagicMock())
Expand Down Expand Up @@ -102,41 +125,7 @@ def test_sync_projects_from_cmdb(self):
project.sync_projects_from_cmdb("user")

Business.objects.update_or_create.assert_has_calls(
[
mock.call(
cc_id=1,
defaults={
"cc_name": "name_1",
"cc_owner": "supplier_account",
"cc_company": 0,
"time_zone": "time_zone",
"life_cycle": "life_cycle",
"status": "enable",
},
),
mock.call(
cc_id=4,
defaults={
"cc_name": "name_4",
"cc_owner": "supplier_account",
"cc_company": 0,
"time_zone": "time_zone",
"life_cycle": "life_cycle",
"status": "enable",
},
),
mock.call(
cc_id=5,
defaults={
"cc_name": "name_5",
"cc_owner": "supplier_account",
"cc_company": 0,
"time_zone": "time_zone",
"life_cycle": "life_cycle",
"status": "enable",
},
),
]
self.generate_business_update_or_create_calls(CaseData.sync_projects_from_cmdb_business_data()["biz_list"])
)

Project.objects.sync_project_from_cmdb_business.assert_called_once_with(
Expand All @@ -146,3 +135,37 @@ def test_sync_projects_from_cmdb(self):
5: {"cc_name": "name_5", "time_zone": "time_zone", "creator": "user"},
}
)

@patch(
CORE_PROJECT_GET_USER_BUSINESS_LIST,
MagicMock(return_value=CaseData.sync_projects_from_cmdb_business_data()["biz_list"][:-1]),
)
@patch(CORE_MODEL_BUSINESS_UPDATE_OR_CREATE, MagicMock())
@patch(CORE_MODEL_PROJECT_SYNC_PROJECT, MagicMock(return_value=["token_0", "token_1"]))
@patch(CORE_MODEL_USER_DEFAULT_PROJECT_INIT_USER_DEFAULT_PROJECT, MagicMock())
@patch(CORE_MODEL_PROJECT_UPDATE_BUSINESS_PROJECT_STATUS, MagicMock())
def test_sync_projects_from_cmdb__business_deleted(self):

project_values_list_qs = MagicMock()
project_values_list_qs.values_list = MagicMock(return_value=[1, 4, 5])
biz_list = CaseData.sync_projects_from_cmdb_business_data()["biz_list"]
with patch(CORE_PROJECT_GET_USER_BUSINESS_LIST, MagicMock(return_value=biz_list)):
with patch(PROJECT_FILTER, MagicMock(return_value=project_values_list_qs)):
project.sync_projects_from_cmdb("user")

# 模拟从 CC 删除最后一个业务
with patch(CORE_PROJECT_GET_USER_BUSINESS_LIST, MagicMock(return_value=biz_list[:-1])):
with patch(PROJECT_FILTER, MagicMock(return_value=project_values_list_qs)):
project.sync_projects_from_cmdb("user")

Business.objects.update_or_create.assert_has_calls(
self.generate_business_update_or_create_calls(biz_list + biz_list[:-1])
)

Project.objects.update_business_project_status.assert_has_calls(
[
mock.call(archived_cc_ids=set(), active_cc_ids={1, 4, 5}),
# cc_id=5 的业务被删除,需要归档
mock.call(archived_cc_ids={5}, active_cc_ids={1, 4}),
]
)

0 comments on commit f2e5467

Please sign in to comment.