perf: Change secret record

pull/15591/head
feng 2025-06-17 17:01:50 +08:00 committed by ZhaoJiSen
parent cfbd162890
commit 00f6c3a5de
3 changed files with 50 additions and 50 deletions

View File

@ -37,7 +37,7 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
) )
self.account_ids = self.execution.snapshot['accounts'] self.account_ids = self.execution.snapshot['accounts']
self.record_map = self.execution.snapshot.get('record_map', {}) # 这个是某个失败的记录重试 self.record_map = self.execution.snapshot.get('record_map', {}) # 这个是某个失败的记录重试
self.name_recorder_mapper = {} # 做个映射,方便后面处理 self.name_record_mapper = {} # 做个映射,方便后面处理
def gen_account_inventory(self, account, asset, h, path_dir): def gen_account_inventory(self, account, asset, h, path_dir):
raise NotImplementedError raise NotImplementedError
@ -113,7 +113,6 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
if host.get('error'): if host.get('error'):
return host return host
host['check_conn_after_change'] = self.execution.snapshot.get('check_conn_after_change', True)
host['ssh_params'] = {} host['ssh_params'] = {}
accounts = self.get_accounts(account) accounts = self.get_accounts(account)
@ -147,7 +146,8 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
continue continue
try: try:
h = self.gen_account_inventory(account, asset, h, path_dir) h, record = self.gen_account_inventory(account, asset, h, path_dir)
h['check_conn_after_change'] = record.execution.snapshot.get('check_conn_after_change', True)
account_secret_task_status.set_status( account_secret_task_status.set_status(
account.id, account.id,
ChangeSecretAccountStatus.PROCESSING, ChangeSecretAccountStatus.PROCESSING,
@ -162,26 +162,26 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
return inventory_hosts return inventory_hosts
@staticmethod @staticmethod
def save_record(recorder): def save_record(record):
recorder.save(update_fields=['error', 'status', 'date_finished']) record.save(update_fields=['error', 'status', 'date_finished'])
@staticmethod @staticmethod
def clear_account_queue_status(account_id): def clear_account_queue_status(account_id):
account_secret_task_status.clear(account_id) account_secret_task_status.clear(account_id)
def on_host_success(self, host, result): def on_host_success(self, host, result):
recorder = self.name_recorder_mapper.get(host) record = self.name_record_mapper.get(host)
if not recorder: if not record:
return return
recorder.status = ChangeSecretRecordStatusChoice.success.value record.status = ChangeSecretRecordStatusChoice.success.value
recorder.date_finished = timezone.now() record.date_finished = timezone.now()
account = recorder.account account = record.account
if not account: if not account:
print("Account not found, deleted ?") print("Account not found, deleted ?")
return return
account.secret = getattr(recorder, 'new_secret', account.secret) account.secret = getattr(record, 'new_secret', account.secret)
account.date_updated = timezone.now() account.date_updated = timezone.now()
account.date_change_secret = timezone.now() account.date_change_secret = timezone.now()
account.change_secret_status = ChangeSecretRecordStatusChoice.success account.change_secret_status = ChangeSecretRecordStatusChoice.success
@ -197,17 +197,17 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
with safe_atomic_db_connection(): with safe_atomic_db_connection():
account.save(update_fields=['secret', 'date_updated', 'date_change_secret', 'change_secret_status']) account.save(update_fields=['secret', 'date_updated', 'date_change_secret', 'change_secret_status'])
self.save_record(recorder) self.save_record(record)
self.clear_account_queue_status(account.id) self.clear_account_queue_status(account.id)
def on_host_error(self, host, error, result): def on_host_error(self, host, error, result):
recorder = self.name_recorder_mapper.get(host) record = self.name_record_mapper.get(host)
if not recorder: if not record:
return return
recorder.status = ChangeSecretRecordStatusChoice.failed.value record.status = ChangeSecretRecordStatusChoice.failed.value
recorder.date_finished = timezone.now() record.date_finished = timezone.now()
recorder.error = error record.error = error
account = recorder.account account = record.account
if not account: if not account:
print("Account not found, deleted ?") print("Account not found, deleted ?")
return return
@ -218,13 +218,13 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
self.summary['fail_accounts'] += 1 self.summary['fail_accounts'] += 1
self.result['fail_accounts'].append( self.result['fail_accounts'].append(
{ {
"asset": str(recorder.asset), "asset": str(record.asset),
"username": recorder.account.username, "username": record.account.username,
} }
) )
super().on_host_error(host, error, result) super().on_host_error(host, error, result)
with safe_atomic_db_connection(): with safe_atomic_db_connection():
account.save(update_fields=['change_secret_status', 'date_change_secret', 'date_updated']) account.save(update_fields=['change_secret_status', 'date_change_secret', 'date_updated'])
self.save_record(recorder) self.save_record(record)
self.clear_account_queue_status(account.id) self.clear_account_queue_status(account.id)

View File

@ -30,28 +30,28 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
record = self.get_or_create_record(asset, account, h['name']) record = self.get_or_create_record(asset, account, h['name'])
new_secret, private_key_path = self.handle_ssh_secret(account.secret_type, record.new_secret, path_dir) new_secret, private_key_path = self.handle_ssh_secret(account.secret_type, record.new_secret, path_dir)
h = self.gen_inventory(h, account, new_secret, private_key_path, asset) h = self.gen_inventory(h, account, new_secret, private_key_path, asset)
return h return h, record
def get_or_create_record(self, asset, account, name): def get_or_create_record(self, asset, account, name):
asset_account_id = f'{asset.id}-{account.id}' asset_account_id = f'{asset.id}-{account.id}'
if asset_account_id in self.record_map: if asset_account_id in self.record_map:
record_id = self.record_map[asset_account_id] record_id = self.record_map[asset_account_id]
recorder = ChangeSecretRecord.objects.filter(id=record_id).first() record = ChangeSecretRecord.objects.filter(id=record_id).first()
else: else:
new_secret = self.get_secret(account) new_secret = self.get_secret(account)
recorder = self.create_record(asset, account, new_secret) record = self.create_record(asset, account, new_secret)
self.name_recorder_mapper[name] = recorder self.name_record_mapper[name] = record
return recorder return record
def create_record(self, asset, account, new_secret): def create_record(self, asset, account, new_secret):
recorder = ChangeSecretRecord( record = ChangeSecretRecord(
asset=asset, account=account, execution=self.execution, asset=asset, account=account, execution=self.execution,
old_secret=account.secret, new_secret=new_secret, old_secret=account.secret, new_secret=new_secret,
comment=f'{account.username}@{asset.address}' comment=f'{account.username}@{asset.address}'
) )
return recorder return record
def check_secret(self): def check_secret(self):
if self.secret_strategy == SecretStrategy.custom \ if self.secret_strategy == SecretStrategy.custom \
@ -61,10 +61,10 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
return True return True
@staticmethod @staticmethod
def get_summary(recorders): def get_summary(records):
total, succeed, failed = 0, 0, 0 total, succeed, failed = 0, 0, 0
for recorder in recorders: for record in records:
if recorder.status == ChangeSecretRecordStatusChoice.success.value: if record.status == ChangeSecretRecordStatusChoice.success.value:
succeed += 1 succeed += 1
else: else:
failed += 1 failed += 1
@ -73,8 +73,8 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
return summary return summary
def print_summary(self): def print_summary(self):
recorders = list(self.name_recorder_mapper.values()) records = list(self.name_record_mapper.values())
summary = self.get_summary(recorders) summary = self.get_summary(records)
print('\n\n' + '-' * 80) print('\n\n' + '-' * 80)
plan_execution_end = _('Plan execution end') plan_execution_end = _('Plan execution end')
print('{} {}\n'.format(plan_execution_end, local_now_filename())) print('{} {}\n'.format(plan_execution_end, local_now_filename()))
@ -86,7 +86,7 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
if self.secret_type and not self.check_secret(): if self.secret_type and not self.check_secret():
return return
recorders = list(self.name_recorder_mapper.values()) records = list(self.name_record_mapper.values())
if self.record_map: if self.record_map:
return return
@ -98,17 +98,17 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
for user in recipients: for user in recipients:
ChangeSecretReportMsg(user, context).publish() ChangeSecretReportMsg(user, context).publish()
if not recorders: if not records:
return return
summary = self.get_summary(recorders) summary = self.get_summary(records)
self.send_recorder_mail(recipients, recorders, summary) self.send_record_mail(recipients, records, summary)
def send_recorder_mail(self, recipients, recorders, summary): def send_record_mail(self, recipients, records, summary):
name = self.execution.snapshot['name'] name = self.execution.snapshot['name']
path = os.path.join(os.path.dirname(settings.BASE_DIR), 'tmp') path = os.path.join(os.path.dirname(settings.BASE_DIR), 'tmp')
filename = os.path.join(path, f'{name}-{local_now_filename()}-{time.time()}.xlsx') filename = os.path.join(path, f'{name}-{local_now_filename()}-{time.time()}.xlsx')
if not self.create_file(recorders, filename): if not self.create_file(records, filename):
return return
for user in recipients: for user in recipients:
@ -121,9 +121,9 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
os.remove(filename) os.remove(filename)
@staticmethod @staticmethod
def create_file(recorders, filename): def create_file(records, filename):
serializer_cls = ChangeSecretRecordBackUpSerializer serializer_cls = ChangeSecretRecordBackUpSerializer
serializer = serializer_cls(recorders, many=True) serializer = serializer_cls(records, many=True)
header = [str(v.label) for v in serializer.child.fields.values()] header = [str(v.label) for v in serializer.child.fields.values()]
rows = [[str(i) for i in row.values()] for row in serializer.data] rows = [[str(i) for i in row.values()] for row in serializer.data]

View File

@ -12,7 +12,7 @@ logger = get_logger(__name__)
class PushAccountManager(BaseChangeSecretPushManager): class PushAccountManager(BaseChangeSecretPushManager):
@staticmethod @staticmethod
def require_update_version(account, recorder): def require_update_version(account, record):
account.skip_history_when_saving = True account.skip_history_when_saving = True
return False return False
@ -31,29 +31,29 @@ class PushAccountManager(BaseChangeSecretPushManager):
secret_type = account.secret_type secret_type = account.secret_type
if not secret: if not secret:
raise ValueError(_('Secret cannot be empty')) raise ValueError(_('Secret cannot be empty'))
self.get_or_create_record(asset, account, h['name']) record = self.get_or_create_record(asset, account, h['name'])
new_secret, private_key_path = self.handle_ssh_secret(secret_type, secret, path_dir) new_secret, private_key_path = self.handle_ssh_secret(secret_type, secret, path_dir)
h = self.gen_inventory(h, account, new_secret, private_key_path, asset) h = self.gen_inventory(h, account, new_secret, private_key_path, asset)
return h return h, record
def get_or_create_record(self, asset, account, name): def get_or_create_record(self, asset, account, name):
asset_account_id = f'{asset.id}-{account.id}' asset_account_id = f'{asset.id}-{account.id}'
if asset_account_id in self.record_map: if asset_account_id in self.record_map:
record_id = self.record_map[asset_account_id] record_id = self.record_map[asset_account_id]
recorder = PushSecretRecord.objects.filter(id=record_id).first() record = PushSecretRecord.objects.filter(id=record_id).first()
else: else:
recorder = self.create_record(asset, account) record = self.create_record(asset, account)
self.name_recorder_mapper[name] = recorder self.name_record_mapper[name] = record
return recorder return record
def create_record(self, asset, account): def create_record(self, asset, account):
recorder = PushSecretRecord( record = PushSecretRecord(
asset=asset, account=account, execution=self.execution, asset=asset, account=account, execution=self.execution,
comment=f'{account.username}@{asset.address}' comment=f'{account.username}@{asset.address}'
) )
return recorder return record
def print_summary(self): def print_summary(self):
print('\n\n' + '-' * 80) print('\n\n' + '-' * 80)