This commit is contained in:
lovvvve 2023-08-17 17:55:06 +08:00 committed by GitHub
commit 13e750c1f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 19 deletions

View File

@ -233,9 +233,12 @@ class CIManager(object):
return CI.get_by_id(unique.ci_id) return CI.get_by_id(unique.ci_id)
@staticmethod @staticmethod
def _delete_ci_by_id(ci_id): def _delete_ci_by_id(ci_id, soft_delete=False):
ci = CI.get_by_id(ci_id) ci = CI.get_by_id(ci_id)
ci.delete() # TODO: soft delete if soft_delete:
ci.soft_delete()
else:
ci.delete()
@staticmethod @staticmethod
def _valid_unique_constraint(type_id, ci_dict, ci_id=None): def _valid_unique_constraint(type_id, ci_dict, ci_id=None):
@ -442,8 +445,8 @@ class CIManager(object):
ci_cache.apply_async([ci_id], queue=CMDB_QUEUE) ci_cache.apply_async([ci_id], queue=CMDB_QUEUE)
@classmethod @classmethod
def delete(cls, ci_id): def delete(cls, ci_id, soft_delete=False):
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id))) ci = CI.get_by_id(ci_id, not soft_delete) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
cls._valid_ci_for_no_read(ci) cls._valid_ci_for_no_read(ci)
@ -454,20 +457,32 @@ class CIManager(object):
attr_names = set([AttributeCache.get(attr.attr_id).name for attr in attrs]) attr_names = set([AttributeCache.get(attr.attr_id).name for attr in attrs])
for attr_name in attr_names: for attr_name in attr_names:
value_table = TableMap(attr_name=attr_name).table value_table = TableMap(attr_name=attr_name).table
for item in value_table.get_by(ci_id=ci_id, to_dict=False): for item in value_table.get_by(ci_id=ci_id, to_dict=False, deleted=not soft_delete):
if soft_delete:
item.soft_delete()
else:
item.delete()
for item in CIRelation.get_by(first_ci_id=ci_id, to_dict=False, deleted=not soft_delete):
ci_relation_delete.apply_async(args=(item.first_ci_id, item.second_ci_id), queue=CMDB_QUEUE)
if soft_delete:
item.soft_delete()
else:
item.delete() item.delete()
for item in CIRelation.get_by(first_ci_id=ci_id, to_dict=False): for item in CIRelation.get_by(second_ci_id=ci_id, to_dict=False, deleted=not soft_delete):
ci_relation_delete.apply_async(args=(item.first_ci_id, item.second_ci_id), queue=CMDB_QUEUE) ci_relation_delete.apply_async(args=(item.first_ci_id, item.second_ci_id), queue=CMDB_QUEUE)
item.delete() if soft_delete:
item.soft_delete()
else:
item.delete()
for item in CIRelation.get_by(second_ci_id=ci_id, to_dict=False): if soft_delete:
ci_relation_delete.apply_async(args=(item.first_ci_id, item.second_ci_id), queue=CMDB_QUEUE) ci.soft_delete()
item.delete() AttributeHistoryManger.add(None, ci_id, [(None, OperateType.SOFT_DELETE, ci_dict, None)], ci.type_id)
else:
ci.delete() # TODO: soft delete ci.delete()
AttributeHistoryManger.add(None, ci_id, [(None, OperateType.DELETE, ci_dict, None)], ci.type_id)
AttributeHistoryManger.add(None, ci_id, [(None, OperateType.DELETE, ci_dict, None)], ci.type_id)
ci_delete.apply_async([ci.id], queue=CMDB_QUEUE) ci_delete.apply_async([ci.id], queue=CMDB_QUEUE)
@ -651,6 +666,10 @@ class CIManager(object):
current_app.logger.warning("cache not hit...............") current_app.logger.warning("cache not hit...............")
return cls._get_cis_from_db(ci_ids, ret_key, fields, value_tables, excludes=excludes) return cls._get_cis_from_db(ci_ids, ret_key, fields, value_tables, excludes=excludes)
@classmethod
def get_soft_delete_ids(cls):
return [ci.get("id") for ci in CI.get_by(deleted=True)]
class CIRelationManager(object): class CIRelationManager(object):
""" """

View File

@ -36,6 +36,7 @@ class OperateType(BaseEnum):
ADD = "0" ADD = "0"
DELETE = "1" DELETE = "1"
UPDATE = "2" UPDATE = "2"
SOFT_DELETE = "3"
class CITypeOperateType(BaseEnum): class CITypeOperateType(BaseEnum):

View File

@ -20,7 +20,7 @@ class FormatMixin(object):
res.pop('secret', None) res.pop('secret', None)
return res return res
@classmethod @classmethod
def from_dict(cls, **kwargs): def from_dict(cls, **kwargs):
from sqlalchemy.sql.sqltypes import Time, Date, DateTime from sqlalchemy.sql.sqltypes import Time, Date, DateTime
@ -86,11 +86,11 @@ class CRUDMixin(FormatMixin):
self.save(flush=flush, commit=commit) self.save(flush=flush, commit=commit)
@classmethod @classmethod
def get_by_id(cls, _id): def get_by_id(cls, _id, with_soft_deleted=False):
if any((isinstance(_id, six.string_types) and _id.isdigit(), if any((isinstance(_id, six.string_types) and _id.isdigit(),
isinstance(_id, (six.integer_types, float))), ): isinstance(_id, (six.integer_types, float))), ):
obj = getattr(cls, "query").get(int(_id)) obj = getattr(cls, "query").get(int(_id))
if obj and not obj.deleted: if obj and (with_soft_deleted or not obj.deleted):
return obj return obj
@classmethod @classmethod

View File

@ -156,3 +156,19 @@ def trigger_notify(notify, ci_id):
for i in notify['mail_to'] if i], subject, body) for i in notify['mail_to'] if i], subject, body)
except Exception as e: except Exception as e:
current_app.logger.error("Send mail failed: {0}".format(str(e))) current_app.logger.error("Send mail failed: {0}".format(str(e)))
@celery.task(name='cmdb.delete_soft_deleted_ci', queue=CMDB_QUEUE)
def delete_soft_deleted_ci(ci_id):
current_app.logger.info("delete_soft_deleted_ci: {}".format(ci_id))
from api.app import create_app
from flask_login import login_user
from api.lib.perm.acl.cache import UserCache
app = create_app()
app.test_request_context().push()
login_user(UserCache.get('worker'))
manager = api.lib.cmdb.ci.CIManager()
manager.delete(ci_id)

View File

@ -1,4 +1,4 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
import time import time
@ -10,7 +10,7 @@ from flask import request
from api.lib.cmdb.cache import CITypeCache from api.lib.cmdb.cache import CITypeCache
from api.lib.cmdb.ci import CIManager from api.lib.cmdb.ci import CIManager
from api.lib.cmdb.ci import CIRelationManager from api.lib.cmdb.ci import CIRelationManager
from api.lib.cmdb.const import ExistPolicy from api.lib.cmdb.const import ExistPolicy, CMDB_QUEUE
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
from api.lib.cmdb.const import RetKey from api.lib.cmdb.const import RetKey
from api.lib.cmdb.perms import has_perm_for_ci from api.lib.cmdb.perms import has_perm_for_ci
@ -240,3 +240,20 @@ class CIAutoDiscoveryStatisticsView(APIView):
def get(self): def get(self):
return self.jsonify(CIManager.get_ad_statistics()) return self.jsonify(CIManager.get_ad_statistics())
class SoftDeleteCis(APIView):
url_prefix = ("/ci/soft_deleted/cis",)
def get(self):
manager = CIManager()
ids = manager.get_soft_delete_ids()
return self.jsonify({"count": len(ids), "ids": ids})
def delete(self):
from api.tasks.cmdb import delete_soft_deleted_ci
manager = CIManager()
ids = manager.get_soft_delete_ids()
for _id in ids:
delete_soft_deleted_ci.apply_async([_id], queue=CMDB_QUEUE)
return self.jsonify(message="add {} ci to celery".format(len(ids)))