mirror of
https://github.com/certd/certd.git
synced 2026-04-23 11:37:23 +08:00
perf: 手动上传证书部署流水线
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { Autoload, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { CertInfoService } from '../monitor/index.js';
|
||||
import { pipelineEmitter } from '@certd/pipeline';
|
||||
import { CertReader, EVENT_CERT_APPLY_SUCCESS } from '@certd/plugin-cert';
|
||||
import { PipelineEvent } from '@certd/pipeline/dist/service/emit.js';
|
||||
import { Autoload, Init, Inject, Scope, ScopeEnum } from "@midwayjs/core";
|
||||
import { CertInfoService } from "../monitor/index.js";
|
||||
import { pipelineEmitter } from "@certd/pipeline";
|
||||
import { CertInfo, EVENT_CERT_APPLY_SUCCESS } from "@certd/plugin-cert";
|
||||
import { PipelineEvent } from "@certd/pipeline/dist/service/emit.js";
|
||||
|
||||
@Autoload()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
@@ -15,8 +15,8 @@ export class AutoEPipelineEmitterRegister {
|
||||
await this.onCertApplySuccess();
|
||||
}
|
||||
async onCertApplySuccess() {
|
||||
pipelineEmitter.on(EVENT_CERT_APPLY_SUCCESS, async (event: PipelineEvent<CertReader>) => {
|
||||
await this.certInfoService.updateCertByPipelineId(event.pipeline.id, event.event);
|
||||
pipelineEmitter.on(EVENT_CERT_APPLY_SUCCESS, async (event: PipelineEvent<{cert:CertInfo,file:string}>) => {
|
||||
await this.certInfoService.updateCertByPipelineId(event.pipeline.id, event.event.cert, event.event.file);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export type UploadCertReq = {
|
||||
certReader: CertReader;
|
||||
fromType?: string;
|
||||
userId?: number;
|
||||
file?:any
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +39,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
});
|
||||
}
|
||||
|
||||
async updateDomains(pipelineId: number, userId: number, domains: string[]) {
|
||||
async updateDomains(pipelineId: number, userId: number, domains: string[],fromType?:string) {
|
||||
const found = await this.repository.findOne({
|
||||
where: {
|
||||
pipelineId,
|
||||
@@ -53,6 +54,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
//create
|
||||
bean.pipelineId = pipelineId;
|
||||
bean.userId = userId;
|
||||
bean.fromType = fromType
|
||||
if (!domains || domains.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -133,7 +135,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
return certReader.toCertInfo();
|
||||
}
|
||||
|
||||
async updateCertByPipelineId(pipelineId: number, certReader: CertReader, fromType = 'pipeline') {
|
||||
async updateCertByPipelineId(pipelineId: number, cert: CertInfo,file?:string,fromType = 'pipeline') {
|
||||
const found = await this.repository.findOne({
|
||||
where: {
|
||||
pipelineId,
|
||||
@@ -141,8 +143,9 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
});
|
||||
const bean = await this.updateCert({
|
||||
id: found?.id,
|
||||
certReader,
|
||||
certReader: new CertReader(cert),
|
||||
fromType,
|
||||
file
|
||||
});
|
||||
return bean;
|
||||
}
|
||||
@@ -165,6 +168,9 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||
bean.expiresTime = certReader.expires;
|
||||
bean.certProvider = certReader.detail.issuer.commonName;
|
||||
bean.userId = userId
|
||||
if(req.file){
|
||||
bean.certFile = req.file
|
||||
}
|
||||
await this.addOrUpdate(bean);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
||||
import { BaseService, CommonException } from "@certd/lib-server";
|
||||
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||
import { EntityManager, Repository } from "typeorm";
|
||||
import { CertInfoEntity } from "../entity/cert-info.js";
|
||||
import { CertInfo, CertReader } from "@certd/plugin-cert";
|
||||
import { PipelineService } from "../../pipeline/service/pipeline-service.js";
|
||||
import { CertInfoService } from "./cert-info-service.js";
|
||||
import { PipelineEntity } from "../../pipeline/entity/pipeline.js";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
export type UploadCertReq = {
|
||||
id?: number;
|
||||
certReader: CertReader;
|
||||
fromType?: string;
|
||||
userId?: number;
|
||||
pipelineId?: number;
|
||||
};
|
||||
|
||||
export type UpdateCertReq = {
|
||||
id: number;
|
||||
cert: CertInfo;
|
||||
userId?: number;
|
||||
};
|
||||
|
||||
export type CreateUploadPipelineReq = {
|
||||
cert: CertInfo;
|
||||
userId: number;
|
||||
pipelineId?: number;
|
||||
pipeline?:{
|
||||
input?:any;
|
||||
notifications?:any[]
|
||||
}
|
||||
};
|
||||
|
||||
@Provide("CertUploadService")
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class CertUploadService extends BaseService<CertInfoEntity> {
|
||||
@InjectEntityModel(CertInfoEntity)
|
||||
repository: Repository<CertInfoEntity>;
|
||||
|
||||
@Inject()
|
||||
pipelineService: PipelineService;
|
||||
@Inject()
|
||||
certInfoService: CertInfoService;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新证书,触发流水线
|
||||
* @param req
|
||||
*/
|
||||
async updateCert(req: UpdateCertReq) {
|
||||
|
||||
const certInfoEntity = await this.certInfoService.info(req.id);
|
||||
if (!certInfoEntity) {
|
||||
throw new CommonException("cert not found");
|
||||
}
|
||||
if(certInfoEntity.fromType !== 'upload') {
|
||||
throw new CommonException("cert can't be custom upload");
|
||||
}
|
||||
await this.uploadCert(this.repository.manager,{
|
||||
id: req.id,
|
||||
fromType: 'upload',
|
||||
userId: req.userId,
|
||||
certReader: new CertReader(req.cert)
|
||||
})
|
||||
|
||||
return {
|
||||
id: certInfoEntity.id,
|
||||
domains: certInfoEntity.domains.split(','),
|
||||
pipelineId: certInfoEntity.pipelineId,
|
||||
fromType: certInfoEntity.fromType,
|
||||
updateTime: certInfoEntity.updateTime,
|
||||
}
|
||||
}
|
||||
|
||||
async createUploadCertPipeline(body:CreateUploadPipelineReq) {
|
||||
const { userId, cert } = body;
|
||||
|
||||
if (!cert) {
|
||||
throw new CommonException("cert can't be empty");
|
||||
}
|
||||
const certReader = new CertReader(cert)
|
||||
return await this.transaction(async (tx:EntityManager)=>{
|
||||
let pipelineId = body.pipelineId;
|
||||
const newCertInfo = await this.uploadCert(tx,{
|
||||
certReader: certReader,
|
||||
fromType: 'upload',
|
||||
userId,
|
||||
pipelineId
|
||||
});
|
||||
|
||||
if(!pipelineId){
|
||||
const pipelineTitle = certReader.getAllDomains()[0] +"上传证书自动部署";
|
||||
const notifications = body.pipeline?.notifications ||[];
|
||||
if(notifications.length === 0){
|
||||
notifications.push({
|
||||
type: "custom",
|
||||
when: ["error", "turnToSuccess", "success"],
|
||||
notificationId: 0,
|
||||
title: "默认通知",
|
||||
});
|
||||
}
|
||||
|
||||
let pipeline = {
|
||||
title: pipelineTitle,
|
||||
runnableType: "pipeline",
|
||||
stages: [
|
||||
{
|
||||
id: nanoid(10),
|
||||
title: "上传证书解析阶段",
|
||||
maxTaskCount: 1,
|
||||
runnableType: "stage",
|
||||
tasks: [
|
||||
{
|
||||
id: nanoid(10),
|
||||
title: "上传证书解析转换",
|
||||
runnableType: "task",
|
||||
steps: [
|
||||
{
|
||||
id: nanoid(10),
|
||||
title: "上传证书解析转换",
|
||||
runnableType: "step",
|
||||
input: {
|
||||
certInfoId: newCertInfo.id,
|
||||
domains: newCertInfo.domains.split(','),
|
||||
...body.pipeline?.input
|
||||
},
|
||||
strategy: {
|
||||
runStrategy: 0, // 正常执行
|
||||
},
|
||||
type: "CertApplyUpload",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
triggers:[],
|
||||
notifications,
|
||||
}
|
||||
const newPipeline = await tx.getRepository(PipelineEntity).save({
|
||||
userId,
|
||||
title: pipelineTitle,
|
||||
type:"cert_upload",
|
||||
content: JSON.stringify(pipeline),
|
||||
keepHistory:20,
|
||||
})
|
||||
|
||||
newCertInfo.pipelineId = newPipeline.id;
|
||||
await tx.getRepository(CertInfoEntity).save({
|
||||
id: newCertInfo.id,
|
||||
pipelineId: newPipeline.id
|
||||
});
|
||||
|
||||
pipelineId = newPipeline.id;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
id:newCertInfo.id,
|
||||
pipelineId: pipelineId,
|
||||
domains: newCertInfo.domains.split(','),
|
||||
fromType: newCertInfo.fromType,
|
||||
updateTime: newCertInfo.updateTime,
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private async uploadCert(tx:EntityManager,req: UploadCertReq) {
|
||||
const bean = new CertInfoEntity();
|
||||
const { id, fromType,userId, certReader } = req;
|
||||
if (id) {
|
||||
bean.id = id;
|
||||
} else {
|
||||
bean.fromType = fromType;
|
||||
bean.userId = userId
|
||||
}
|
||||
const certInfo = certReader.toCertInfo();
|
||||
bean.certInfo = JSON.stringify(certInfo);
|
||||
bean.applyTime = new Date().getTime();
|
||||
const domains = certReader.detail.domains.altNames;
|
||||
bean.domains = domains.join(',');
|
||||
bean.domain = domains[0];
|
||||
bean.domainCount = domains.length;
|
||||
bean.expiresTime = certReader.expires;
|
||||
bean.certProvider = certReader.detail.issuer.commonName;
|
||||
if (req.pipelineId){
|
||||
bean.pipelineId = req.pipelineId;
|
||||
}
|
||||
|
||||
await tx.getRepository(CertInfoEntity).save(bean);
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import {ICertApplyUploadService} from "@certd/plugin-cert";
|
||||
import {IMidwayContext, Inject, Provide} from "@midwayjs/core";
|
||||
import {CertInfoService} from "../../monitor/index.js";
|
||||
import {CertUploadService} from "../../monitor/service/cert-upload-service.js";
|
||||
|
||||
@Provide("CertApplyUploadService")
|
||||
export class CertApplyUploadService implements ICertApplyUploadService {
|
||||
@Inject()
|
||||
ctx : IMidwayContext
|
||||
|
||||
async getCertInfo(opts: { certId: number; userId: number; }) {
|
||||
const certInfoService = this.ctx.getApp().getApplicationContext().get<CertInfoService>("CertInfoService")
|
||||
const { certId, userId } = opts;
|
||||
return await certInfoService.getCertInfo({
|
||||
certId,
|
||||
userId: Number(userId),
|
||||
});
|
||||
};
|
||||
async updateCert(opts: { certId: any; userId: any; cert: any; }){
|
||||
const certUploadService = this.ctx.getApp().getApplicationContext().get<CertUploadService>("CertUploadService")
|
||||
return await certUploadService.updateCert({
|
||||
id:opts.certId,
|
||||
userId:opts.userId,
|
||||
cert:opts.cert
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,6 @@ import { NotificationService } from "./notification-service.js";
|
||||
import { NotificationGetter } from "./notification-getter.js";
|
||||
import { UserSuiteEntity, UserSuiteService } from "@certd/commercial-core";
|
||||
import { CertInfoService } from "../../monitor/service/cert-info-service.js";
|
||||
import {CertApplyUploadService} from "./cert-apply-upload-service.js";
|
||||
|
||||
const runningTasks: Map<string | number, Executor> = new Map();
|
||||
|
||||
@@ -93,8 +92,6 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
@Inject()
|
||||
certInfoService: CertInfoService;
|
||||
|
||||
@Inject()
|
||||
certApplyUploadService: CertApplyUploadService;
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
@@ -196,10 +193,11 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
await this.registerTriggerById(bean.id);
|
||||
|
||||
//保存域名信息到certInfo表
|
||||
if(bean.from !== 'cert_upload'){
|
||||
await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains);
|
||||
let fromType = 'pipeline';
|
||||
if(bean.type === 'cert_upload') {
|
||||
fromType = 'upload';
|
||||
}
|
||||
|
||||
await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains,fromType);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -483,9 +481,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||
sysInfo.title = siteInfo.title;
|
||||
}
|
||||
const serviceContainer = {
|
||||
CertApplyUploadService: this.certApplyUploadService
|
||||
}
|
||||
const serviceContainer = {}
|
||||
const serviceGetter = {
|
||||
get:(name: string) => {
|
||||
return serviceContainer[name]
|
||||
|
||||
Reference in New Issue
Block a user