mirror of https://github.com/certd/certd
perf: 触发证书重新申请input变化对比规则优化,减少升级版本后触发申请证书的情况
parent
84fd3b250d
commit
c46a2a9a39
|
@ -181,6 +181,9 @@ export class RunnableCollection {
|
|||
if (runnable?.status) {
|
||||
runnable.status.status = ResultType.none;
|
||||
runnable.status.result = ResultType.none;
|
||||
runnable.status.inputHash = "";
|
||||
// @ts-ignore
|
||||
runnable.input = {};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,6 @@ export type HistoryResultGroup = {
|
|||
};
|
||||
};
|
||||
export type HistoryResult = {
|
||||
// input: any;
|
||||
inputHash?: string;
|
||||
output: any;
|
||||
files?: FileItem[];
|
||||
|
|
|
@ -5,6 +5,7 @@ import { CertReader } from "./cert-reader.js";
|
|||
import JSZip from "jszip";
|
||||
import { CertConverter } from "./convert.js";
|
||||
import fs from "fs";
|
||||
import { pick } from "lodash-es";
|
||||
|
||||
export { CertReader };
|
||||
export type { CertInfo };
|
||||
|
@ -203,11 +204,36 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||
return null;
|
||||
}
|
||||
|
||||
const inputChanged = this.ctx.inputChanged;
|
||||
let inputChanged = this.ctx.inputChanged;
|
||||
if (inputChanged) {
|
||||
this.logger.info("input hash 有变更,检查是否需要重新申请证书");
|
||||
//判断域名有没有变更
|
||||
/**
|
||||
* "renewDays": 20,
|
||||
* "certApplyPlugin": "CertApply",
|
||||
* "sslProvider": "letsencrypt",
|
||||
* "privateKeyType": "rsa_2048_pkcs1",
|
||||
* "dnsProviderType": "aliyun",
|
||||
* "domains": [
|
||||
* "*.handsfree.work"
|
||||
* ],
|
||||
* "email": "xiaojunnuo@qq.com",
|
||||
* "dnsProviderAccess": 3,
|
||||
* "useProxy": false,
|
||||
* "skipLocalVerify": false,
|
||||
* "successNotify": true,
|
||||
* "pfxPassword": "123456"
|
||||
*/
|
||||
const checkInputChanges = ["domains", "sslProvider", "privateKeyType", "dnsProviderType", "dnsProviderAccess", "pfxPassword"];
|
||||
const oldInput = JSON.stringify(pick(this.lastStatus?.input, checkInputChanges));
|
||||
const thisInput = JSON.stringify(pick(this, checkInputChanges));
|
||||
inputChanged = oldInput !== thisInput;
|
||||
|
||||
if (inputChanged) {
|
||||
this.logger.info("输入参数变更,准备申请新证书");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
let oldCert: CertReader | undefined = undefined;
|
||||
try {
|
||||
|
|
|
@ -6,7 +6,6 @@ import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, Edi
|
|||
import { useUserStore } from "/@/store/modules/user";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
import { message } from "ant-design-vue";
|
||||
import { DoVerify } from "./api";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
|
@ -125,9 +124,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
}),
|
||||
form: {
|
||||
component: {
|
||||
onDictChange: ({ form, dict }) => {
|
||||
onDictChange: ({ form, dict }: any) => {
|
||||
if (!form.cnameProviderId) {
|
||||
const item = dict.data.find((item) => item.isDefault);
|
||||
const item = dict.data.find((item: any) => item.isDefault);
|
||||
if (item) {
|
||||
form.cnameProviderId = item.id;
|
||||
}
|
||||
|
@ -180,7 +179,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
message.success("验证成功");
|
||||
row.status = "valid";
|
||||
}
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
console.error(e);
|
||||
message.error(e.message);
|
||||
} finally {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="title">
|
||||
<div>{{ item.name }}({{ item.fileName }})</div>
|
||||
<fs-copyable :model-value="item.content" :button="{ show: false }">
|
||||
<a-tag type="success">复制</a-tag>
|
||||
<a-tag color="success">复制</a-tag>
|
||||
</fs-copyable>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -155,7 +155,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
|
|||
const viewCert = async (row: any) => {
|
||||
const cert = await api.GetCert(row.id);
|
||||
if (!cert) {
|
||||
notification.error({ message: "还没有产生证书,请先运行流水线" });
|
||||
notification.error({ message: "请先运行一次流水线" });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
<fs-icon
|
||||
v-if="!editMode"
|
||||
class="pointer color-blue ml-2"
|
||||
title="重新运行此步骤"
|
||||
title="完全重新运行此步骤"
|
||||
icon="SyncOutlined"
|
||||
@click="run(item.id)"
|
||||
></fs-icon>
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
"iconv-lite": "^0.6.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"jszip": "^3.10.1",
|
||||
"koa-send": "^5.0.1",
|
||||
"kubernetes-client": "^9.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
|
|
@ -102,7 +102,7 @@ export class AsyncSsh2Client {
|
|||
let iconv: any = await import('iconv-lite');
|
||||
iconv = iconv.default;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.logger.info(`执行命令:[${this.connConf.host}][exec]: ` + script);
|
||||
this.logger.info(`执行命令:[${this.connConf.host}][exec]: \n` + script);
|
||||
this.conn.exec(script, (err: Error, stream: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
|
@ -274,7 +274,7 @@ export class SshClient {
|
|||
let { script } = options;
|
||||
const { connectConf } = options;
|
||||
|
||||
this.logger.info('命令:', script);
|
||||
// this.logger.info('命令:', script);
|
||||
return await this._call({
|
||||
connectConf,
|
||||
callable: async (conn: AsyncSsh2Client) => {
|
||||
|
|
|
@ -4,6 +4,8 @@ import path from 'path';
|
|||
import dayjs from 'dayjs';
|
||||
import { SshAccess, SshClient } from '../../plugin-host/index.js';
|
||||
import { AbstractPlusTaskPlugin } from '@certd/plugin-plus';
|
||||
import JSZip from 'jszip';
|
||||
import * as os from 'node:os';
|
||||
|
||||
const defaultBackupDir = 'certd_backup';
|
||||
const defaultFilePrefix = 'db-backup';
|
||||
|
@ -100,16 +102,25 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
|
|||
return;
|
||||
}
|
||||
|
||||
this.logger.info('当前备份方式:', this.backupMode);
|
||||
//本地压缩
|
||||
const zip = new JSZip();
|
||||
zip.file(dbPath);
|
||||
const content = await zip.generateAsync({ type: 'nodebuffer' });
|
||||
const dbZipFilename = `${this.filePrefix}.${dayjs().format('YYYYMMDD.HHmmss')}.sqlite.zip`;
|
||||
const dbZipPath = path.resolve(os.tmpdir(), dbZipFilename);
|
||||
await fs.promises.writeFile(dbZipPath, content);
|
||||
this.logger.info(`数据库文件压缩完成:${dbZipPath}`);
|
||||
|
||||
this.logger.info('开始备份,当前备份方式:', this.backupMode);
|
||||
const backupDir = this.backupDir || defaultBackupDir;
|
||||
const backupFile = `${backupDir}/${this.filePrefix}.${dayjs().format('YYYYMMDD.HHmmss')}.sqlite`;
|
||||
const backupFilePath = `${backupDir}/${dbZipFilename}`;
|
||||
|
||||
if (this.backupMode === 'local') {
|
||||
await this.localBackup(dbPath, backupDir, backupFile);
|
||||
await this.localBackup(dbPath, backupDir, backupFilePath);
|
||||
} else if (this.backupMode === 'ssh') {
|
||||
await this.sshBackup(dbPath, backupDir, backupFile);
|
||||
await this.sshBackup(dbPath, backupDir, backupFilePath);
|
||||
} else if (this.backupMode === 'oss') {
|
||||
await this.ossBackup(dbPath, backupDir, backupFile);
|
||||
await this.ossBackup(dbPath, backupDir, backupFilePath);
|
||||
} else {
|
||||
throw new Error(`不支持的备份方式:${this.backupMode}`);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue