perf: 部署插件支持宝塔、易盾云等

pull/148/head
xiaojunnuo 2024-08-30 18:50:53 +08:00
parent bee20c7f51
commit ee617095ef
22 changed files with 120 additions and 112 deletions

View File

@ -13,8 +13,12 @@ const defaultOpts = {
termsOfServiceAgreed: false, termsOfServiceAgreed: false,
skipChallengeVerification: false, skipChallengeVerification: false,
challengePriority: ['http-01', 'dns-01'], challengePriority: ['http-01', 'dns-01'],
challengeCreateFn: async () => { throw new Error('Missing challengeCreateFn()'); }, challengeCreateFn: async () => {
challengeRemoveFn: async () => { throw new Error('Missing challengeRemoveFn()'); }, throw new Error('Missing challengeCreateFn()');
},
challengeRemoveFn: async () => {
throw new Error('Missing challengeRemoveFn()');
},
}; };
/** /**
@ -209,6 +213,7 @@ module.exports = async (client, userOpts) => {
} }
log(`[auto] challengeGroups:${allChallengePromises.length}`); log(`[auto] challengeGroups:${allChallengePromises.length}`);
function runAllPromise(tasks) { function runAllPromise(tasks) {
let promise = Promise.resolve(); let promise = Promise.resolve();
tasks.forEach((task) => { tasks.forEach((task) => {
@ -228,47 +233,48 @@ module.exports = async (client, userOpts) => {
return Promise.all(results); return Promise.all(results);
} }
try { log(`开始challenge${allChallengePromises.length}`);
log(`开始challenge${allChallengePromises.length}`); let i = 0;
let i = 0; // eslint-disable-next-line no-restricted-syntax
// eslint-disable-next-line no-restricted-syntax for (const challengePromises of allChallengePromises) {
for (const challengePromises of allChallengePromises) { i += 1;
i += 1; log(`开始第${i}`);
log(`开始第${i}`); if (opts.signal && opts.signal.aborted) {
if (opts.signal && opts.signal.aborted) { throw new Error('用户取消');
throw new Error('用户取消'); }
}
try {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
await runPromisePa(challengePromises); await runPromisePa(challengePromises);
} }
log('challenge结束');
// log('[auto] Waiting for challenge valid status');
// await Promise.all(challengePromises);
/**
* Finalize order and download certificate
*/
log('[auto] Finalizing order and downloading certificate');
const finalized = await client.finalizeOrder(order, opts.csr);
return await client.getCertificate(finalized, opts.preferredChain);
}
catch (e) {
log(`证书申请失败${e.message}`);
throw e;
}
finally {
log(`清理challenge痕迹length:${clearTasks.length}`);
try {
await runAllPromise(clearTasks);
}
catch (e) { catch (e) {
log('清理challenge失败'); log(`证书申请失败${e.message}`);
log(e); throw e;
}
finally {
log(`清理challenge痕迹length:${clearTasks.length}`);
try {
// eslint-disable-next-line no-await-in-loop
await runAllPromise(clearTasks);
}
catch (e) {
log('清理challenge失败');
log(e);
}
} }
} }
log('challenge结束');
// log('[auto] Waiting for challenge valid status');
// await Promise.all(challengePromises);
/**
* Finalize order and download certificate
*/
log('[auto] Finalizing order and downloading certificate');
const finalized = await client.finalizeOrder(order, opts.csr);
const res = await client.getCertificate(finalized, opts.preferredChain);
return res;
// try { // try {
// await Promise.allSettled(challengePromises); // await Promise.allSettled(challengePromises);
// } // }

View File

@ -109,7 +109,7 @@ export class RunHistory {
logError(runnable: Runnable, e: Error) { logError(runnable: Runnable, e: Error) {
// @ts-ignore // @ts-ignore
this._loggers[runnable.id].error(`[${runnable.title}]<id:${runnable.id}> [${runnable.runnableType}]`, e); this._loggers[runnable.id].error(`[${runnable.title}]<id:${runnable.id}> [${runnable.runnableType}]`, e.stack);
} }
finally(runnable: Runnable) { finally(runnable: Runnable) {

View File

@ -40,6 +40,8 @@ export type PluginDefine = Registrable & {
dest: string; dest: string;
type: "computed"; type: "computed";
}[]; }[];
needPlus?: boolean;
}; };
export type ITaskPlugin = { export type ITaskPlugin = {

View File

@ -1,8 +1,31 @@
import axios from "axios"; import axios from "axios";
// @ts-ignore
import qs from "qs";
import { logger } from "./util.log.js"; import { logger } from "./util.log.js";
import { Logger } from "log4js"; import { Logger } from "log4js";
export class HttpError extends Error {
request?: { url: string; method: string; data?: any };
response?: { data: any };
status?: number;
statusText?: string;
constructor(error: any) {
if (!error) {
return;
}
super(error.message);
this.name = error.name;
this.stack = error.stack;
this.status = error?.response?.status;
this.statusText = error?.response?.statusText;
this.request = {
url: error?.response?.config?.url,
method: error?.response?.config?.method,
data: error?.response?.config?.data,
};
this.response = {
data: error?.response?.data,
};
}
}
/** /**
* @description * @description
*/ */
@ -12,13 +35,6 @@ export function createAxiosService({ logger }: { logger: Logger }) {
// 请求拦截 // 请求拦截
service.interceptors.request.use( service.interceptors.request.use(
(config: any) => { (config: any) => {
if (config.formData) {
config.data = qs.stringify(config.formData, {
arrayFormat: "indices",
allowDots: true,
}); // 序列化请求参数
delete config.formData;
}
logger.info(`http request:${config.url}method:${config.method}`); logger.info(`http request:${config.url}method:${config.method}`);
return config; return config;
}, },
@ -50,26 +66,12 @@ export function createAxiosService({ logger }: { logger: Logger }) {
// case 505: error.message = 'HTTP版本不受支持'; break // case 505: error.message = 'HTTP版本不受支持'; break
// default: break // default: break
// } // }
logger.error(`请求出错url:${error?.response?.config.url},method:${error?.response?.config?.method},status:${error?.response?.status}`); logger.error(
logger.info("返回数据:", JSON.stringify(error?.response?.data)); `请求出错status:${error?.response?.status},statusText:${error?.response?.statusText},url:${error?.config?.url},method:${error?.config?.method}`
delete error.config; );
const data = error?.response?.data; logger.error("返回数据:", JSON.stringify(error?.response?.data));
if (!data) { const err = new HttpError(error);
error.message = data.message || data.msg || data.error || data; return Promise.reject(err);
}
if (error?.response) {
return Promise.reject({
status: error?.response?.status,
statusText: error?.response?.statusText,
request: {
url: error?.response?.config?.url,
method: error?.response?.config?.method,
data: error?.response?.data,
},
data: error?.response?.data,
});
}
return Promise.reject(error);
} }
); );
return service; return service;

View File

@ -1,6 +1,9 @@
koa: koa:
port: 7001 port: 7001
#plus:
# server:
# baseUrl: 'http://127.0.0.1:11007'
plus: plus:
server: server:
baseUrl: 'http://127.0.0.1:11007' baseUrl: 'https://api.ai.handsfree.work'

View File

@ -28,6 +28,7 @@
"@certd/midway-flyway-js": "^1.22.6", "@certd/midway-flyway-js": "^1.22.6",
"@certd/pipeline": "^1.24.0", "@certd/pipeline": "^1.24.0",
"@certd/plugin-cert": "^1.24.0", "@certd/plugin-cert": "^1.24.0",
"@certd/plugin-plus": "^1.24.0",
"@koa/cors": "^3.4.3", "@koa/cors": "^3.4.3",
"@midwayjs/bootstrap": "^3.16.2", "@midwayjs/bootstrap": "^3.16.2",
"@midwayjs/cache": "^3.14.0", "@midwayjs/cache": "^3.14.0",

View File

@ -49,7 +49,7 @@ export class PermissionController extends CrudController<PermissionService> {
@Post('/delete', { summary: 'sys:auth:per:remove' }) @Post('/delete', { summary: 'sys:auth:per:remove' })
async delete( async delete(
@Query('id') @Query('id')
id id : number
) { ) {
return await super.delete(id); return await super.delete(id);
} }

View File

@ -1,12 +1,4 @@
import { import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
ALL,
Body,
Controller,
Inject,
Post,
Provide,
Query,
} from '@midwayjs/core';
import { CrudController } from '../../../basic/crud-controller.js'; import { CrudController } from '../../../basic/crud-controller.js';
import { RoleService } from '../service/role-service.js'; import { RoleService } from '../service/role-service.js';
@ -55,7 +47,7 @@ export class RoleController extends CrudController<RoleService> {
@Post('/delete', { summary: 'sys:auth:role:remove' }) @Post('/delete', { summary: 'sys:auth:role:remove' })
async delete( async delete(
@Query('id') @Query('id')
id id: number
) { ) {
return await super.delete(id); return await super.delete(id);
} }
@ -63,7 +55,7 @@ export class RoleController extends CrudController<RoleService> {
@Post('/getPermissionTree', { summary: 'sys:auth:role:view' }) @Post('/getPermissionTree', { summary: 'sys:auth:role:view' })
async getPermissionTree( async getPermissionTree(
@Query('id') @Query('id')
id id: number
) { ) {
const ret = await this.service.getPermissionTreeByRoleId(id); const ret = await this.service.getPermissionTreeByRoleId(id);
return this.ok(ret); return this.ok(ret);
@ -72,7 +64,7 @@ export class RoleController extends CrudController<RoleService> {
@Post('/getPermissionIds', { summary: 'sys:auth:role:view' }) @Post('/getPermissionIds', { summary: 'sys:auth:role:view' })
async getPermissionIds( async getPermissionIds(
@Query('id') @Query('id')
id id: number
) { ) {
const ret = await this.service.getPermissionIdsByRoleId(id); const ret = await this.service.getPermissionIdsByRoleId(id);
return this.ok(ret); return this.ok(ret);

View File

@ -73,7 +73,7 @@ export class UserController extends CrudController<UserService> {
@Post('/delete', { summary: 'sys:auth:user:remove' }) @Post('/delete', { summary: 'sys:auth:user:remove' })
async delete( async delete(
@Query('id') @Query('id')
id id : number
) { ) {
return await super.delete(id); return await super.delete(id);
} }

View File

@ -49,13 +49,13 @@ export class UserSettingsController extends CrudController<UserSettingsService>
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id); await this.service.checkUserId(id, this.ctx.user.id);
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id); await this.service.checkUserId(id, this.ctx.user.id);
return super.delete(id); return super.delete(id);
} }

View File

@ -41,19 +41,19 @@ export class AccessController extends CrudController<AccessService> {
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id); await this.service.checkUserId(id, this.ctx.user.id);
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id); await this.service.checkUserId(id, this.ctx.user.id);
return super.delete(id); return super.delete(id);
} }
@Post('/define', { summary: Constants.per.authOnly }) @Post('/define', { summary: Constants.per.authOnly })
async define(@Query('type') type) { async define(@Query('type') type:string) {
const access = this.service.getDefineByType(type); const access = this.service.getDefineByType(type);
return this.ok(access); return this.ok(access);
} }

View File

@ -13,7 +13,7 @@ export class DnsProviderController extends BaseController {
service: DnsProviderService; service: DnsProviderService;
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Query(ALL) query) { async list(@Query(ALL) query:any) {
query.userId = this.ctx.user.id; query.userId = this.ctx.user.id;
const list = this.service.getList(); const list = this.service.getList();
return this.ok(list); return this.ok(list);

View File

@ -99,14 +99,14 @@ export class HistoryController extends CrudController<HistoryService> {
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id) { async delete(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
await super.delete(id); await super.delete(id);
return this.ok(); return this.ok();
} }
@Post('/deleteByIds', { summary: Constants.per.authOnly }) @Post('/deleteByIds', { summary: Constants.per.authOnly })
async deleteByIds(@Body(ALL) body) { async deleteByIds(@Body(ALL) body: any) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), body.ids); await this.authService.checkEntityUserId(this.ctx, this.getService(), body.ids);
const isAdmin = await this.authService.isAdmin(this.ctx); const isAdmin = await this.authService.isAdmin(this.ctx);
const userId = isAdmin ? null : this.ctx.user.id; const userId = isAdmin ? null : this.ctx.user.id;
@ -115,21 +115,21 @@ export class HistoryController extends CrudController<HistoryService> {
} }
@Post('/detail', { summary: Constants.per.authOnly }) @Post('/detail', { summary: Constants.per.authOnly })
async detail(@Query('id') id) { async detail(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
const detail = await this.service.detail(id); const detail = await this.service.detail(id);
return this.ok(detail); return this.ok(detail);
} }
@Post('/logs', { summary: Constants.per.authOnly }) @Post('/logs', { summary: Constants.per.authOnly })
async logs(@Query('id') id) { async logs(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.logService, id); await this.authService.checkEntityUserId(this.ctx, this.logService, id);
const logInfo = await this.logService.info(id); const logInfo = await this.logService.info(id);
return this.ok(logInfo); return this.ok(logInfo);
} }
@Post('/files', { summary: Constants.per.authOnly }) @Post('/files', { summary: Constants.per.authOnly })
async files(@Query('pipelineId') pipelineId, @Query('historyId') historyId) { async files(@Query('pipelineId') pipelineId: number, @Query('historyId') historyId: number) {
await this.authService.checkEntityUserId(this.ctx, this.service, historyId); await this.authService.checkEntityUserId(this.ctx, this.service, historyId);
const files = await this.getFiles(historyId, pipelineId); const files = await this.getFiles(historyId, pipelineId);
return this.ok(files); return this.ok(files);
@ -153,7 +153,7 @@ export class HistoryController extends CrudController<HistoryService> {
} }
@Get('/download', { summary: Constants.per.authOnly }) @Get('/download', { summary: Constants.per.authOnly })
async download(@Query('pipelineId') pipelineId, @Query('historyId') historyId, @Query('fileId') fileId) { async download(@Query('pipelineId') pipelineId: number, @Query('historyId') historyId: number, @Query('fileId') fileId: string) {
await this.authService.checkEntityUserId(this.ctx, this.service, historyId); await this.authService.checkEntityUserId(this.ctx, this.service, historyId);
const files = await this.getFiles(historyId, pipelineId); const files = await this.getFiles(historyId, pipelineId);
const file = files.find(f => f.id === fileId); const file = files.find(f => f.id === fileId);

View File

@ -73,28 +73,28 @@ export class PipelineController extends CrudController<PipelineService> {
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id) { async delete(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
await this.service.delete(id); await this.service.delete(id);
return this.ok({}); return this.ok({});
} }
@Post('/detail', { summary: Constants.per.authOnly }) @Post('/detail', { summary: Constants.per.authOnly })
async detail(@Query('id') id) { async detail(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
const detail = await this.service.detail(id); const detail = await this.service.detail(id);
return this.ok(detail); return this.ok(detail);
} }
@Post('/trigger', { summary: Constants.per.authOnly }) @Post('/trigger', { summary: Constants.per.authOnly })
async trigger(@Query('id') id) { async trigger(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
await this.service.trigger(id); await this.service.trigger(id);
return this.ok({}); return this.ok({});
} }
@Post('/cancel', { summary: Constants.per.authOnly }) @Post('/cancel', { summary: Constants.per.authOnly })
async cancel(@Query('historyId') historyId) { async cancel(@Query('historyId') historyId: number) {
await this.authService.checkEntityUserId(this.ctx, this.historyService, historyId); await this.authService.checkEntityUserId(this.ctx, this.historyService, historyId);
await this.service.cancel(historyId); await this.service.cancel(historyId);
return this.ok({}); return this.ok({});

View File

@ -13,14 +13,14 @@ export class PluginController extends BaseController {
service: PluginService; service: PluginService;
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Query(ALL) query) { async list(@Query(ALL) query: any) {
query.userId = this.ctx.user.id; query.userId = this.ctx.user.id;
const list = this.service.getList(); const list = this.service.getList();
return this.ok(list); return this.ok(list);
} }
@Post('/groups', { summary: Constants.per.authOnly }) @Post('/groups', { summary: Constants.per.authOnly })
async groups(@Query(ALL) query) { async groups(@Query(ALL) query: any) {
query.userId = this.ctx.user.id; query.userId = this.ctx.user.id;
const group = this.service.getGroups(); const group = this.service.getGroups();
return this.ok(group); return this.ok(group);

View File

@ -50,7 +50,7 @@ export class AccessService extends BaseService<AccessEntity> implements IAccessS
const json = JSON.parse(setting); const json = JSON.parse(setting);
let oldSetting = {}; let oldSetting = {};
let encryptSetting = {}; let encryptSetting = {};
const firstEncrypt = !oldSettingEntity.encryptSetting || oldSettingEntity.encryptSetting === '{}'; const firstEncrypt = !oldSettingEntity || !oldSettingEntity.encryptSetting || oldSettingEntity.encryptSetting === '{}';
if (oldSettingEntity) { if (oldSettingEntity) {
oldSetting = JSON.parse(oldSettingEntity.setting || '{}'); oldSetting = JSON.parse(oldSettingEntity.setting || '{}');
encryptSetting = JSON.parse(oldSettingEntity.encryptSetting || '{}'); encryptSetting = JSON.parse(oldSettingEntity.encryptSetting || '{}');

View File

@ -44,7 +44,7 @@ export class HistoryService extends BaseService<HistoryEntity> {
} }
} }
async detail(historyId: string) { async detail(historyId: number) {
const entity = await this.info(historyId); const entity = await this.info(historyId);
const log = await this.logService.info(historyId); const log = await this.logService.info(historyId);
return new HistoryDetail(entity, log); return new HistoryDetail(entity, log);

View File

@ -45,13 +45,13 @@ export class SysSettingsController extends CrudController<SysSettingsService> {
return super.update(bean); return super.update(bean);
} }
@Post('/info', { summary: 'sys:settings:view' }) @Post('/info', { summary: 'sys:settings:view' })
async info(@Query('id') id) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id); await this.service.checkUserId(id, this.ctx.user.id);
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: 'sys:settings:edit' }) @Post('/delete', { summary: 'sys:settings:edit' })
async delete(@Query('id') id) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id); await this.service.checkUserId(id, this.ctx.user.id);
return super.delete(id); return super.delete(id);
} }

View File

@ -1,4 +1,5 @@
export * from '@certd/plugin-cert'; export * from '@certd/plugin-cert';
export * from '@certd/plugin-plus';
export * from './plugin-aliyun/index.js'; export * from './plugin-aliyun/index.js';
export * from './plugin-tencent/index.js'; export * from './plugin-tencent/index.js';
export * from './plugin-host/index.js'; export * from './plugin-host/index.js';

View File

@ -31,8 +31,8 @@ export class TencentDnsProvider extends AbstractDnsProvider {
}, },
}, },
}; };
const dnspodSdk: any = await import('tencentcloud-sdk-nodejs/tencentcloud/services/dnspod/v20210323/index.js'); const dnspodSdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/dnspod/v20210323/index.js');
const DnspodClient = dnspodSdk.Client; const DnspodClient = dnspodSdk.v20210323.Client;
// 实例化要请求产品的client对象,clientProfile是可选的 // 实例化要请求产品的client对象,clientProfile是可选的
this.client = new DnspodClient(clientConfig); this.client = new DnspodClient(clientConfig);
} }

View File

@ -92,14 +92,14 @@ export class DeployToClbPlugin extends AbstractTaskPlugin {
accessId!: string; accessId!: string;
client: any; client: any;
ClbClient: any;
async onInstance() { async onInstance() {
this.client = await this.getClient(); this.client = await this.getClient();
} }
async getClient() { async getClient() {
const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/clb/index.js'); const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/clb/v20180317/index.js');
const ClbClient = sdk.clb.v20180317.Client; this.ClbClient = sdk.v20180317.Client;
const accessProvider = (await this.accessService.getById(this.accessId)) as TencentAccess; const accessProvider = (await this.accessService.getById(this.accessId)) as TencentAccess;
@ -117,7 +117,7 @@ export class DeployToClbPlugin extends AbstractTaskPlugin {
}, },
}; };
return new ClbClient(clientConfig); return new this.ClbClient(clientConfig);
} }
async execute(): Promise<void> { async execute(): Promise<void> {

View File

@ -88,12 +88,13 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
}) })
cert!: any; cert!: any;
sdk: any; TkeClient: any;
K8sClient: any; K8sClient: any;
async onInstance() { async onInstance() {
// const TkeClient = this.tencentcloud.tke.v20180525.Client; // const TkeClient = this.tencentcloud.tke.v20180525.Client;
this.sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/tke/v20220501/index.js'); const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/tke/v20220501/index.js');
this.TkeClient = sdk.v20220501.Client;
const k8sSdk = await import('@certd/lib-k8s'); const k8sSdk = await import('@certd/lib-k8s');
this.K8sClient = k8sSdk.K8sClient; this.K8sClient = k8sSdk.K8sClient;
} }
@ -139,7 +140,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
}, },
}; };
return new this.sdk.Client(clientConfig); return new this.TkeClient(clientConfig);
} }
async getTkeKubeConfig(client: any, clusterId: string) { async getTkeKubeConfig(client: any, clusterId: string) {