perf: 上传到主机插件支持复制到本机路径

pull/68/head
xiaojunnuo 2024-05-30 10:54:18 +08:00
parent d9eb927b0a
commit 92446c3399
7 changed files with 107 additions and 29 deletions

View File

@ -1,12 +1,23 @@
import { AbstractTaskPlugin, Decorator, HttpClient, IAccessService, IContext, IsTaskPlugin, RunStrategy, Step, TaskInput, TaskOutput } from "@certd/pipeline";
import {
AbstractTaskPlugin,
Decorator,
HttpClient,
IAccessService,
IContext,
IsTaskPlugin,
RunStrategy,
Step,
TaskInput,
TaskOutput
} from "@certd/pipeline";
import dayjs from "dayjs";
import { AcmeService, CertInfo } from "./acme";
import {AcmeService, CertInfo} from "./acme";
import _ from "lodash";
import { Logger } from "log4js";
import { DnsProviderDefine, dnsProviderRegistry } from "../../dns-provider";
import { CertReader } from "./cert-reader";
import {Logger} from "log4js";
import {DnsProviderDefine, dnsProviderRegistry} from "../../dns-provider";
import {CertReader} from "./cert-reader";
import JSZip from "jszip";
import { fileUtils } from "@certd/pipeline";
export { CertReader };
export type { CertInfo };
@ -150,7 +161,7 @@ export class CertApplyPlugin extends AbstractTaskPlugin {
const cert: CertInfo = certReader.toCertInfo();
this.cert = cert;
// this.logger.info(JSON.stringify(certReader.detail));
const applyTime = dayjs(certReader.detail.validity.notBefore).format("YYYYMMDDHHmmss");
const applyTime = dayjs(certReader.detail.validity.notBefore).format("YYYYMMDD_HHmmss");
await this.zipCert(cert, applyTime);
}
@ -162,8 +173,7 @@ export class CertApplyPlugin extends AbstractTaskPlugin {
const filename = `cert_${domain_name}_${applyTime}.zip`;
const content = await zip.generateAsync({ type: "nodebuffer" });
this.saveFile(filename, content);
this.logger.info(`getFileRootDir:${fileUtils.getFileRootDir("11")}`);
this.logger.info(`保存文件:${filename}`);
this.logger.info(`已保存文件:${filename}`);
}
/**

View File

@ -10,3 +10,23 @@
justify-content: center;
align-items: center;
}
.cd-icon-button{
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.cd-flex{
display: flex;
justify-content: left;
align-items: center;
}
.cd-flex-inline{
display: inline-flex;
justify-content: left;
align-items: center;
}

View File

@ -55,6 +55,10 @@ h1, h2, h3, h4, h5, h6 {
margin-left:5px;
}
.mr-5{
margin-right: 5px;
}
.mt-10{
margin-top:10px;
}

View File

@ -64,7 +64,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}
},
rowHandle: {
width: "150px"
width: "180px"
},
table: {
rowSelection: {

View File

@ -1,6 +1,9 @@
<template>
<div class="pi-access-selector">
<span v-if="target.name" class="mlr-5">{{ target.name }}</span>
<span v-if="target.name" class="mr-5 cd-flex-inline">
<span class="mr-5">{{ target.name }}</span>
<fs-icon class="cd-icon-button" icon="ion:close-circle-outline" @click="clear"></fs-icon>
</span>
<span v-else class="mlr-5 gray">请选择</span>
<a-button @click="chooseForm.open"></a-button>
<a-form-item-rest v-if="chooseForm.show">
@ -42,6 +45,13 @@ export default defineComponent({
target.value = await api.GetObj(value);
}
}
function clear(){
selectedId.value = "";
target.value = null
ctx.emit("update:modelValue", selectedId.value);
}
watch(
() => {
return props.modelValue;
@ -89,7 +99,9 @@ export default defineComponent({
}
});
return {
clear,
target,
selectedId,
providerDefine,

View File

@ -23,6 +23,9 @@ export class AccessService
async getById(id: any): Promise<any> {
const entity = await this.info(id);
if (entity == null) {
throw new Error(`该授权配置不存在,请确认是否已被删除:id=${id}`);
}
// const access = accessRegistry.get(entity.type);
const setting = JSON.parse(entity.setting);
return {
@ -38,5 +41,4 @@ export class AccessService
getDefineByType(type: string) {
return accessRegistry.getDefine(type);
}
}

View File

@ -14,6 +14,7 @@ import * as fs from 'fs';
@IsTaskPlugin({
name: 'uploadCertToHost',
title: '上传证书到主机',
desc: '也支持复制证书到本机',
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
@ -53,10 +54,22 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
name: 'pi-access-selector',
type: 'ssh',
},
rules: [{ required: true, message: '此项必填' }],
rules: [{ required: false, message: '' }],
})
accessId!: string;
@TaskInput({
title: '复制到当前主机',
helper:
'开启后将直接复制到当前主机某个目录由于是docker启动实际上复制到的是docker容器内的目录你需要事先在docker-compose.yaml中配置主机目录映射 volumes: /your_target_path:/your_target_path',
component: {
name: 'a-switch',
value: false,
vModel: 'checked',
},
})
copyToThisHost!: boolean;
@TaskOutput({
title: '证书保存路径',
})
@ -74,29 +87,46 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
this.accessService = this.ctx.accessService;
this.logger = this.ctx.logger;
}
copyFile(srcFile: string, destFile: string) {
const dir = destFile.substring(0, destFile.lastIndexOf('/'));
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.copyFileSync(srcFile, destFile);
}
async execute(): Promise<void> {
const { crtPath, keyPath, cert, accessId } = this;
const certReader = new CertReader(cert);
const connectConf = await this.accessService.getById(accessId);
const sshClient = new SshClient(this.logger);
const saveCrtPath = certReader.saveToFile('crt');
const saveKeyPath = certReader.saveToFile('key');
await sshClient.uploadFiles({
connectConf,
transports: [
{
localPath: saveCrtPath,
remotePath: crtPath,
},
{
localPath: saveKeyPath,
remotePath: keyPath,
},
],
});
this.logger.info('证书上传成功crtPath=', crtPath, ',keyPath=', keyPath);
if (this.copyToThisHost) {
this.copyFile(saveCrtPath, crtPath);
this.copyFile(saveKeyPath, keyPath);
this.logger.info('证书复制成功crtPath=', crtPath, ',keyPath=', keyPath);
} else {
if (!accessId) {
throw new Error('主机登录授权配置不能为空');
}
const connectConf = await this.accessService.getById(accessId);
const sshClient = new SshClient(this.logger);
await sshClient.uploadFiles({
connectConf,
transports: [
{
localPath: saveCrtPath,
remotePath: crtPath,
},
{
localPath: saveKeyPath,
remotePath: keyPath,
},
],
});
this.logger.info('证书上传成功crtPath=', crtPath, ',keyPath=', keyPath);
}
//删除临时文件
fs.unlinkSync(saveCrtPath);