mirror of https://github.com/certd/certd
feat: midway注解方式编写插件
parent
717d203622
commit
e4ec4e1404
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.0.0",
|
||||
"npmClient": "yarn"
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
"private": true,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"lerna": "^3.18.4"
|
||||
"lerna": "^6.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "lerna bootstrap --hoist",
|
||||
|
@ -11,6 +11,9 @@
|
|||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.20"
|
||||
}
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/**"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1c0e55a5339ef0ac92f96726c4c61e6918908730
|
||||
Subproject commit 138c736ce6468e208a1055fd6289b8c2c8361306
|
|
@ -1,7 +1,5 @@
|
|||
import { Registrable } from "../registry";
|
||||
import { accessRegistry } from "./registry";
|
||||
import { FormItemProps } from "../d.ts";
|
||||
import { AbstractAccess } from "./abstract-access";
|
||||
|
||||
export type AccessInputDefine = FormItemProps & {
|
||||
title: string;
|
||||
|
@ -13,5 +11,5 @@ export type AccessDefine = Registrable & {
|
|||
};
|
||||
};
|
||||
export interface IAccessService {
|
||||
getById(id: any): Promise<AbstractAccess>;
|
||||
getById(id: any): Promise<any>;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
saveModule,
|
||||
} from "@midwayjs/decorator";
|
||||
import { AccessDefine, AccessInputDefine } from "./api";
|
||||
import _ from "lodash-es";
|
||||
import _ from "lodash";
|
||||
import { accessRegistry } from "./registry";
|
||||
|
||||
// 提供一个唯一 key
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import { ConcurrencyStrategy, Pipeline, ResultType, Runnable, RunStrategy, Stage, Step, Task } from "../d.ts";
|
||||
import _ from "lodash";
|
||||
import { RunHistory } from "./run-history";
|
||||
import { pluginRegistry, ITaskPlugin, PluginDefine } from "../plugin";
|
||||
import { PluginDefine, pluginRegistry } from "../plugin";
|
||||
import { ContextFactory, IContext } from "./context";
|
||||
import { IStorage } from "./storage";
|
||||
import { logger } from "../utils/util.log";
|
||||
import { Logger } from "log4js";
|
||||
import { request } from "../utils/util.request";
|
||||
import { IAccessService } from "../access";
|
||||
import { Registrable, RegistryItem } from "../registry";
|
||||
import { RegistryItem } from "../registry";
|
||||
|
||||
export class Executor {
|
||||
userId: any;
|
||||
pipeline: Pipeline;
|
||||
|
@ -136,7 +137,7 @@ export class Executor {
|
|||
private async runStep(step: Step) {
|
||||
//执行任务
|
||||
const plugin: RegistryItem = pluginRegistry.get(step.type);
|
||||
const context = {
|
||||
const context: any = {
|
||||
logger: this.runtime.loggers[step.id],
|
||||
accessService: this.accessService,
|
||||
pipelineContext: this.pipelineContext,
|
||||
|
@ -159,7 +160,9 @@ export class Executor {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
_.forEach(define.autowire, (item, key: string) => {
|
||||
instance[key] = context[key];
|
||||
});
|
||||
|
||||
const res = await instance.execute();
|
||||
|
||||
|
|
|
@ -1,18 +1,5 @@
|
|||
// src/decorator/memoryCache.decorator.ts
|
||||
import {
|
||||
attachClassMetadata,
|
||||
attachPropertyDataToClass,
|
||||
createCustomPropertyDecorator,
|
||||
getClassMetadata,
|
||||
listModule,
|
||||
listPropertyDataFromClass,
|
||||
Provide,
|
||||
saveClassMetadata,
|
||||
saveModule,
|
||||
Scope,
|
||||
ScopeEnum,
|
||||
} from "@midwayjs/decorator";
|
||||
import _ from "lodash-es";
|
||||
import { getClassMetadata, listModule, Provide, saveClassMetadata, saveModule, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { dnsProviderRegistry } from "./registry";
|
||||
import { DnsProviderDefine } from "./api";
|
||||
|
||||
|
|
|
@ -5,6 +5,5 @@ export * from "./registry";
|
|||
export * from "./dns-provider";
|
||||
export * from "./plugin";
|
||||
export * from "./utils";
|
||||
export * from "./decorator";
|
||||
export * from "./midway";
|
||||
export * from "./context";
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { Config, Configuration, getClassMetadata, Inject, listModule, listPropertyDataFromClass, Logger } from "@midwayjs/decorator";
|
||||
import _ from "lodash-es";
|
||||
import { Config, Configuration, Inject, Logger } from "@midwayjs/decorator";
|
||||
// @ts-ignore
|
||||
import { ILogger } from "@midwayjs/logger";
|
||||
import { IMidwayContainer, MidwayDecoratorService } from "@midwayjs/core";
|
||||
import { pluginRegistry } from "../plugin";
|
||||
import { registerPlugins } from "../plugin/decorator";
|
||||
import { registerAccess } from "../access/decorator";
|
||||
import { registerDnsProviders } from "../dns-provider";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Registrable } from "../registry";
|
||||
import { pluginRegistry } from "./registry";
|
||||
import { FormItemProps } from "../d.ts";
|
||||
|
||||
export enum ContextScope {
|
||||
|
@ -33,6 +32,7 @@ export type PluginDefine = Registrable & {
|
|||
};
|
||||
|
||||
export interface ITaskPlugin {
|
||||
onInit(): Promise<void>;
|
||||
execute(): Promise<void>;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
// src/decorator/memoryCache.decorator.ts
|
||||
import {
|
||||
attachClassMetadata,
|
||||
attachPropertyDataToClass,
|
||||
createCustomPropertyDecorator,
|
||||
getClassMetadata,
|
||||
listModule,
|
||||
listPropertyDataFromClass,
|
||||
Provide,
|
||||
saveClassMetadata,
|
||||
saveModule,
|
||||
Scope,
|
||||
ScopeEnum,
|
||||
} from "@midwayjs/decorator";
|
||||
import _ from "lodash-es";
|
||||
import _ from "lodash";
|
||||
import { pluginRegistry } from "./registry";
|
||||
import { PluginDefine, TaskInputDefine, TaskOutputDefine } from "./api";
|
||||
|
||||
|
@ -33,11 +28,11 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
|||
},
|
||||
target
|
||||
);
|
||||
// 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx
|
||||
Scope(ScopeEnum.Prototype)(target);
|
||||
// // 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx
|
||||
// Scope(ScopeEnum.Prototype)(target);
|
||||
|
||||
// 调用一下 Provide 装饰器,这样用户的 class 可以省略写 @Provide() 装饰器了
|
||||
Provide()(target);
|
||||
// Provide()(target);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import log4js, { LoggingEvent } from "log4js";
|
||||
import log4js, { LoggingEvent, Logger } from "log4js";
|
||||
|
||||
const OutputAppender = {
|
||||
configure: (config: any, layouts: any, findAppender: any, levels: any) => {
|
||||
|
@ -32,3 +32,4 @@ export function buildLogger(write: (text: string) => void) {
|
|||
});
|
||||
return logger;
|
||||
}
|
||||
export type LOGGER = Logger;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"@certd/plugin-util": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"log4js": "^6.7.1",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"vue-tsc": "^0.38.9",
|
||||
"@alicloud/cs20151215": "^3.0.3",
|
||||
|
@ -40,7 +41,6 @@
|
|||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"log4js": "^6.3.0",
|
||||
"mocha": "^10.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.8.4",
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
import { AbstractAccess, IsAccess } from "@certd/pipeline";
|
||||
import { IsAccess, IsAccessInput } from "@certd/pipeline";
|
||||
|
||||
@IsAccess({
|
||||
name: "aliyun",
|
||||
title: "阿里云授权",
|
||||
desc: "",
|
||||
input: {
|
||||
accessKeyId: {
|
||||
title: "accessKeyId",
|
||||
component: {
|
||||
placeholder: "accessKeyId",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
accessKeySecret: {
|
||||
title: "accessKeySecret",
|
||||
component: {
|
||||
placeholder: "accessKeySecret",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
export class AliyunAccess extends AbstractAccess {
|
||||
export class AliyunAccess {
|
||||
@IsAccessInput({
|
||||
title: "accessKeyId",
|
||||
component: {
|
||||
placeholder: "accessKeyId",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessKeyId = "";
|
||||
@IsAccessInput({
|
||||
title: "accessKeySecret",
|
||||
component: {
|
||||
placeholder: "accessKeySecret",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessKeySecret = "";
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Core from "@alicloud/pop-core";
|
||||
import _ from "lodash";
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IDnsProvider, IsDnsProvider, RemoveRecordOptions } from "@certd/pipeline";
|
||||
import { CreateRecordOptions, IDnsProvider, IsDnsProvider, RemoveRecordOptions } from "@certd/pipeline";
|
||||
import { Logger } from "log4js";
|
||||
|
||||
@IsDnsProvider({
|
||||
name: "aliyun",
|
||||
|
@ -8,11 +9,10 @@ import { AbstractDnsProvider, CreateRecordOptions, IDnsProvider, IsDnsProvider,
|
|||
desc: "阿里云DNS解析提供商",
|
||||
accessType: "aliyun",
|
||||
})
|
||||
export class AliyunDnsProvider extends AbstractDnsProvider implements IDnsProvider {
|
||||
export class AliyunDnsProvider implements IDnsProvider {
|
||||
client: any;
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
access: any;
|
||||
logger!: Logger;
|
||||
async onInit() {
|
||||
const access: any = this.access;
|
||||
this.client = new Core({
|
||||
|
|
|
@ -1,59 +1,69 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin } from "@certd/pipeline";
|
||||
import { Autowire, IAccessService, IsTaskPlugin, ITaskPlugin, LOGGER, RunStrategy, TaskInput } from "@certd/pipeline";
|
||||
import dayjs from "dayjs";
|
||||
import Core from "@alicloud/pop-core";
|
||||
import RPCClient from "@alicloud/pop-core";
|
||||
import { AliyunAccess } from "../../access";
|
||||
import { Inject } from "@midwayjs/core";
|
||||
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "DeployCertToAliyunCDN",
|
||||
title: "部署证书至阿里云CDN",
|
||||
desc: "依赖证书申请前置任务,自动部署域名证书至阿里云CDN",
|
||||
input: {
|
||||
domainName: {
|
||||
title: "CDN加速域名",
|
||||
helper: "你在阿里云上配置的CDN加速域名,比如certd.docmirror.cn",
|
||||
required: true,
|
||||
},
|
||||
certName: {
|
||||
title: "证书名称",
|
||||
helper: "上传后将以此名称作为前缀备注",
|
||||
},
|
||||
cert: {
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
accessId: {
|
||||
title: "Access授权",
|
||||
helper: "阿里云授权AccessKeyId、AccessKeySecret",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "aliyun",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@IsTaskPlugin({
|
||||
name: "DeployCertToAliyunCDN",
|
||||
title: "部署证书至阿里云CDN",
|
||||
desc: "依赖证书申请前置任务,自动部署域名证书至阿里云CDN",
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
output: {},
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class DeployCertToAliyunCDN extends AbstractPlugin implements TaskPlugin {
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
export class DeployCertToAliyunCDN implements ITaskPlugin {
|
||||
@TaskInput({
|
||||
title: "CDN加速域名",
|
||||
helper: "你在阿里云上配置的CDN加速域名,比如certd.docmirror.cn",
|
||||
required: true,
|
||||
})
|
||||
domainName!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "证书名称",
|
||||
helper: "上传后将以此名称作为前缀备注",
|
||||
})
|
||||
certName!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "Access授权",
|
||||
helper: "阿里云授权AccessKeyId、AccessKeySecret",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "aliyun",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@Inject()
|
||||
accessService!: IAccessService;
|
||||
|
||||
@Autowire()
|
||||
logger!: LOGGER;
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
async onInit() {}
|
||||
async execute(): Promise<void> {
|
||||
console.log("开始部署证书到阿里云cdn");
|
||||
const access = (await this.accessService.getById(input.accessId)) as AliyunAccess;
|
||||
const access = (await this.accessService.getById(this.accessId)) as AliyunAccess;
|
||||
const client = this.getClient(access);
|
||||
const params = await this.buildParams(input);
|
||||
const params = await this.buildParams();
|
||||
await this.doRequest(client, params);
|
||||
console.log("部署完成");
|
||||
return {};
|
||||
}
|
||||
|
||||
getClient(access: AliyunAccess) {
|
||||
|
@ -65,13 +75,12 @@ export class DeployCertToAliyunCDN extends AbstractPlugin implements TaskPlugin
|
|||
});
|
||||
}
|
||||
|
||||
async buildParams(input: TaskInput) {
|
||||
const { certName, domainName } = input;
|
||||
const CertName = (certName ?? "certd") + "-" + dayjs().format("YYYYMMDDHHmmss");
|
||||
const cert = input.cert;
|
||||
async buildParams() {
|
||||
const CertName = (this.certName ?? "certd") + "-" + dayjs().format("YYYYMMDDHHmmss");
|
||||
const cert: any = this.cert;
|
||||
return {
|
||||
RegionId: "cn-hangzhou",
|
||||
DomainName: domainName,
|
||||
DomainName: this.domainName,
|
||||
ServerCertificateStatus: "on",
|
||||
CertName: CertName,
|
||||
CertType: "upload",
|
||||
|
|
|
@ -1,70 +1,81 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin } from "@certd/pipeline";
|
||||
import { Autowire, IAccessService, IsTaskPlugin, ITaskPlugin, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||
import Core from "@alicloud/pop-core";
|
||||
import { AliyunAccess } from "../../access";
|
||||
import { appendTimeSuffix, checkRet, ZoneOptions } from "../../utils";
|
||||
import { Logger } from "log4js";
|
||||
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "uploadCertToAliyun",
|
||||
title: "上传证书到阿里云",
|
||||
desc: "",
|
||||
input: {
|
||||
name: {
|
||||
title: "证书名称",
|
||||
helper: "证书上传后将以此参数作为名称前缀",
|
||||
},
|
||||
regionId: {
|
||||
title: "大区",
|
||||
value: "cn-hangzhou",
|
||||
component: {
|
||||
name: "a-select",
|
||||
vModel: "value",
|
||||
options: ZoneOptions,
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
cert: {
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
accessId: {
|
||||
title: "Access授权",
|
||||
helper: "阿里云授权AccessKeyId、AccessKeySecret",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "aliyun",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@IsTaskPlugin({
|
||||
name: "uploadCertToAliyun",
|
||||
title: "上传证书到阿里云",
|
||||
desc: "",
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
output: {
|
||||
aliyunCertId: {
|
||||
title: "上传成功后的阿里云CertId",
|
||||
},
|
||||
},
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class UploadCertToAliyun extends AbstractPlugin implements TaskPlugin {
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
export class UploadCertToAliyun implements ITaskPlugin {
|
||||
@TaskInput({
|
||||
title: "证书名称",
|
||||
|
||||
helper: "证书上传后将以此参数作为名称前缀",
|
||||
})
|
||||
name!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "大区",
|
||||
value: "cn-hangzhou",
|
||||
component: {
|
||||
name: "a-select",
|
||||
vModel: "value",
|
||||
options: ZoneOptions,
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
regionId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: any;
|
||||
|
||||
@TaskInput({
|
||||
title: "Access授权",
|
||||
helper: "阿里云授权AccessKeyId、AccessKeySecret",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "aliyun",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@TaskOutput({
|
||||
title: "上传成功后的阿里云CertId",
|
||||
})
|
||||
aliyunCertId!: string;
|
||||
|
||||
@Autowire()
|
||||
accessService!: IAccessService;
|
||||
|
||||
@Autowire()
|
||||
logger!: Logger;
|
||||
|
||||
async execute(): Promise<void> {
|
||||
console.log("开始部署证书到阿里云cdn");
|
||||
const access = (await this.accessService.getById(input.accessId)) as AliyunAccess;
|
||||
const access = (await this.accessService.getById(this.accessId)) as AliyunAccess;
|
||||
const client = this.getClient(access);
|
||||
const { name, cert } = input;
|
||||
const certName = appendTimeSuffix(name);
|
||||
const certName = appendTimeSuffix(this.name);
|
||||
const params = {
|
||||
RegionId: input.regionId || "cn-hangzhou",
|
||||
RegionId: this.regionId || "cn-hangzhou",
|
||||
Name: certName,
|
||||
Cert: cert.crt,
|
||||
Key: cert.key,
|
||||
Cert: this.cert.crt,
|
||||
Key: this.cert.key,
|
||||
};
|
||||
|
||||
const requestOption = {
|
||||
|
@ -74,7 +85,9 @@ export class UploadCertToAliyun extends AbstractPlugin implements TaskPlugin {
|
|||
const ret = (await client.request("CreateUserCertificate", params, requestOption)) as any;
|
||||
checkRet(ret);
|
||||
this.logger.info("证书上传成功:aliyunCertId=", ret.CertId);
|
||||
return { aliyunCertId: ret.CertId };
|
||||
|
||||
//output
|
||||
this.aliyunCertId = ret.CertId;
|
||||
}
|
||||
|
||||
getClient(aliyunProvider: AliyunAccess) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
},
|
||||
"devDependencies": {
|
||||
"log4js": "^6.7.1",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"vue-tsc": "^0.38.9",
|
||||
"@alicloud/cs20151215": "^3.0.3",
|
||||
|
@ -36,7 +37,6 @@
|
|||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"log4js": "^6.3.0",
|
||||
"mocha": "^10.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.8.4",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export * from "@certd/plugin-aliyun";
|
||||
// export * from "@certd/plugin-aliyun";
|
||||
export * from "@certd/plugin-cert";
|
||||
export * from "@certd/plugin-tencent";
|
||||
export * from "@certd/plugin-host";
|
||||
// export * from "@certd/plugin-host";
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"@certd/pipeline": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"log4js": "^6.7.1",
|
||||
"dayjs": "^1.11.6",
|
||||
"lodash": "^4.17.21",
|
||||
"@types/lodash": "^4.14.186",
|
||||
|
@ -36,7 +37,6 @@
|
|||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"log4js": "^6.3.0",
|
||||
"mocha": "^10.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.8.4",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @ts-ignore
|
||||
import * as acme from "@certd/acme-client";
|
||||
import _ from "lodash";
|
||||
import { AbstractDnsProvider, IDnsProvider } from "@certd/pipeline";
|
||||
import { IDnsProvider } from "@certd/pipeline";
|
||||
import { Challenge } from "@certd/acme-client/types/rfc8555";
|
||||
import { Logger } from "log4js";
|
||||
import { IContext } from "@certd/pipeline/src/core/context";
|
||||
|
@ -132,7 +132,7 @@ export class AcmeService {
|
|||
}
|
||||
}
|
||||
|
||||
async order(options: { email: string; domains: string | string[]; dnsProvider: AbstractDnsProvider; csrInfo: any; isTest?: boolean }) {
|
||||
async order(options: { email: string; domains: string | string[]; dnsProvider: any; csrInfo: any; isTest?: boolean }) {
|
||||
const { email, isTest, domains, csrInfo, dnsProvider } = options;
|
||||
const client: acme.Client = await this.getAcmeClient(email, isTest);
|
||||
|
||||
|
|
|
@ -1,123 +1,164 @@
|
|||
import { AbstractDnsProvider, AbstractPlugin, dnsProviderRegistry, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin } from "@certd/pipeline";
|
||||
import {
|
||||
Autowire,
|
||||
dnsProviderRegistry,
|
||||
HttpClient,
|
||||
IAccessService,
|
||||
IContext,
|
||||
IsTaskPlugin,
|
||||
ITaskPlugin,
|
||||
RunStrategy,
|
||||
TaskInput,
|
||||
TaskOutput,
|
||||
} from "@certd/pipeline";
|
||||
import forge from "node-forge";
|
||||
import dayjs from "dayjs";
|
||||
import { AcmeService } from "./acme";
|
||||
import _ from "lodash";
|
||||
import { Logger } from "log4js";
|
||||
|
||||
export type CertInfo = {
|
||||
crt: string;
|
||||
key: string;
|
||||
csr: string;
|
||||
};
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "CertApply",
|
||||
title: "证书申请",
|
||||
desc: "免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
||||
@IsTaskPlugin({
|
||||
name: "CertApply",
|
||||
title: "证书申请",
|
||||
desc: "免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
||||
default: {
|
||||
input: {
|
||||
domains: {
|
||||
title: "域名",
|
||||
component: {
|
||||
name: "a-select",
|
||||
vModel: "value",
|
||||
mode: "tags",
|
||||
open: false,
|
||||
},
|
||||
required: true,
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper:
|
||||
"支持通配符域名,例如: *.foo.com 、 *.test.handsfree.work\n" +
|
||||
"支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
||||
"多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com)\n" +
|
||||
"输入一个回车之后,再输入下一个",
|
||||
},
|
||||
email: {
|
||||
title: "邮箱",
|
||||
component: {
|
||||
name: "a-input",
|
||||
vModel: "value",
|
||||
},
|
||||
required: true,
|
||||
helper: "请输入邮箱",
|
||||
},
|
||||
dnsProviderType: {
|
||||
title: "DNS提供商",
|
||||
component: {
|
||||
name: "pi-dns-provider-selector",
|
||||
},
|
||||
required: true,
|
||||
helper: "请选择dns解析提供商",
|
||||
},
|
||||
dnsProviderAccess: {
|
||||
title: "DNS解析授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
},
|
||||
required: true,
|
||||
helper: "请选择dns解析提供商授权",
|
||||
},
|
||||
renewDays: {
|
||||
title: "更新天数",
|
||||
component: {
|
||||
name: "a-input-number",
|
||||
vModel: "value",
|
||||
},
|
||||
required: true,
|
||||
helper: "到期前多少天后更新证书",
|
||||
},
|
||||
forceUpdate: {
|
||||
title: "强制更新",
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
helper: "是否强制重新申请证书",
|
||||
},
|
||||
renewDays: 20,
|
||||
forceUpdate: false,
|
||||
},
|
||||
default: {
|
||||
input: {
|
||||
renewDays: 20,
|
||||
forceUpdate: false,
|
||||
},
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.AlwaysRun,
|
||||
},
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.AlwaysRun,
|
||||
},
|
||||
output: {
|
||||
cert: {
|
||||
key: "cert",
|
||||
type: "CertInfo",
|
||||
title: "域名证书",
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class CertApplyPlugin extends AbstractPlugin implements TaskPlugin {
|
||||
export class CertApplyPlugin implements ITaskPlugin {
|
||||
@TaskInput({
|
||||
title: "域名",
|
||||
component: {
|
||||
name: "a-select",
|
||||
vModel: "value",
|
||||
mode: "tags",
|
||||
open: false,
|
||||
},
|
||||
required: true,
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper:
|
||||
"支持通配符域名,例如: *.foo.com 、 *.test.handsfree.work\n" +
|
||||
"支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
||||
"多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com)\n" +
|
||||
"输入一个回车之后,再输入下一个",
|
||||
})
|
||||
domains!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "邮箱",
|
||||
component: {
|
||||
name: "a-input",
|
||||
vModel: "value",
|
||||
},
|
||||
required: true,
|
||||
helper: "请输入邮箱",
|
||||
})
|
||||
email!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "DNS提供商",
|
||||
component: {
|
||||
name: "pi-dns-provider-selector",
|
||||
},
|
||||
required: true,
|
||||
helper: "请选择dns解析提供商",
|
||||
})
|
||||
dnsProviderType!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "DNS解析授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
},
|
||||
required: true,
|
||||
helper: "请选择dns解析提供商授权",
|
||||
})
|
||||
dnsProviderAccess!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "更新天数",
|
||||
component: {
|
||||
name: "a-input-number",
|
||||
vModel: "value",
|
||||
},
|
||||
required: true,
|
||||
helper: "到期前多少天后更新证书",
|
||||
})
|
||||
renewDays!: number;
|
||||
|
||||
@TaskInput({
|
||||
title: "强制更新",
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
helper: "是否强制重新申请证书",
|
||||
})
|
||||
forceUpdate!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "CsrInfo",
|
||||
})
|
||||
csrInfo: any;
|
||||
|
||||
// @ts-ignore
|
||||
acme: AcmeService;
|
||||
protected async onInit() {
|
||||
|
||||
@Autowire()
|
||||
logger!: Logger;
|
||||
|
||||
@Autowire()
|
||||
userContext!: IContext;
|
||||
|
||||
@Autowire()
|
||||
accessService!: IAccessService;
|
||||
|
||||
@Autowire()
|
||||
http!: HttpClient;
|
||||
|
||||
@Autowire()
|
||||
pipelineContext!: IContext;
|
||||
|
||||
@TaskOutput({
|
||||
title: "域名证书",
|
||||
})
|
||||
cert?: CertInfo;
|
||||
|
||||
async onInit() {
|
||||
this.acme = new AcmeService({ userContext: this.userContext, logger: this.logger });
|
||||
}
|
||||
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
const oldCert = await this.condition(input);
|
||||
async execute(): Promise<void> {
|
||||
const oldCert = await this.condition();
|
||||
if (oldCert != null) {
|
||||
return {
|
||||
cert: oldCert,
|
||||
};
|
||||
return this.output(oldCert);
|
||||
}
|
||||
const cert = await this.doCertApply(input);
|
||||
return { cert };
|
||||
const cert = await this.doCertApply();
|
||||
return this.output(cert);
|
||||
}
|
||||
|
||||
output(cert: any) {
|
||||
this.cert = cert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否更新证书
|
||||
* @param input
|
||||
*/
|
||||
async condition(input: TaskInput) {
|
||||
if (input.forceUpdate) {
|
||||
async condition() {
|
||||
if (this.forceUpdate) {
|
||||
return null;
|
||||
}
|
||||
let oldCert;
|
||||
|
@ -131,7 +172,7 @@ export class CertApplyPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
return null;
|
||||
}
|
||||
|
||||
const ret = this.isWillExpire(oldCert.expires, input.renewDays);
|
||||
const ret = this.isWillExpire(oldCert.expires, this.renewDays);
|
||||
if (!ret.isWillExpire) {
|
||||
this.logger.info(`证书还未过期:过期时间${dayjs(oldCert.expires).format("YYYY-MM-DD HH:mm:ss")},剩余${ret.leftDays}天`);
|
||||
return oldCert;
|
||||
|
@ -140,11 +181,11 @@ export class CertApplyPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
return null;
|
||||
}
|
||||
|
||||
async doCertApply(input: TaskInput) {
|
||||
const email = input["email"];
|
||||
const domains = input["domains"];
|
||||
const dnsProviderType = input["dnsProviderType"];
|
||||
const dnsProviderAccessId = input["dnsProviderAccess"];
|
||||
async doCertApply() {
|
||||
const email = this["email"];
|
||||
const domains = this["domains"];
|
||||
const dnsProviderType = this["dnsProviderType"];
|
||||
const dnsProviderAccessId = this["dnsProviderAccess"];
|
||||
const csrInfo = _.merge(
|
||||
{
|
||||
country: "CN",
|
||||
|
@ -154,7 +195,7 @@ export class CertApplyPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
organizationUnit: "IT Department",
|
||||
emailAddress: email,
|
||||
},
|
||||
input["csrInfo"]
|
||||
this.csrInfo
|
||||
);
|
||||
this.logger.info("开始申请证书,", email, domains);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"ssh2": "^0.8.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"log4js": "^6.3.0",
|
||||
"log4js": "^6.7.1",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20",
|
||||
"@types/lodash": "^4.14.186",
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
"tencentcloud-sdk-nodejs": "^4.0.44"
|
||||
},
|
||||
"devDependencies": {
|
||||
"log4js": "^6.7.1",
|
||||
"axios": "^0.21.1",
|
||||
"log4js": "^6.3.0",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20",
|
||||
"@types/lodash": "^4.14.186",
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { IAccessService, IsTaskPlugin, RunStrategy, TaskInput, ITaskPlugin } from "@certd/pipeline";
|
||||
import { IAccessService, IsTaskPlugin, RunStrategy, TaskInput, ITaskPlugin, LOGGER } from "@certd/pipeline";
|
||||
import tencentcloud from "tencentcloud-sdk-nodejs/index";
|
||||
import { TencentAccess } from "../../access";
|
||||
import { Inject } from "@midwayjs/decorator";
|
||||
import { ILogger } from "@midwayjs/core";
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: "DeployCertToTencentCDN",
|
||||
|
@ -52,7 +51,10 @@ export class DeployToCdnPlugin implements ITaskPlugin {
|
|||
accessService!: IAccessService;
|
||||
|
||||
@Inject()
|
||||
logger!: ILogger;
|
||||
logger!: LOGGER;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
async onInit() {}
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const accessProvider: TencentAccess = (await this.accessService.getById(this.accessId)) as TencentAccess;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { IAccessService, IsTaskPlugin, ITaskPlugin, RunStrategy, TaskInput, utils } from "@certd/pipeline";
|
||||
import { IAccessService, IsTaskPlugin, ITaskPlugin, LOGGER, RunStrategy, TaskInput, utils } from "@certd/pipeline";
|
||||
import tencentcloud from "tencentcloud-sdk-nodejs/index";
|
||||
import { TencentAccess } from "../../access";
|
||||
import dayjs from "dayjs";
|
||||
import { Inject } from "@midwayjs/decorator";
|
||||
import { ILogger } from "@midwayjs/core";
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: "DeployCertToTencentCLB",
|
||||
|
@ -77,8 +76,10 @@ export class DeployToClbPlugin implements ITaskPlugin {
|
|||
accessService!: IAccessService;
|
||||
|
||||
@Inject()
|
||||
logger!: ILogger;
|
||||
logger!: LOGGER;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
async onInit() {}
|
||||
async execute(): Promise<void> {
|
||||
const accessProvider = (await this.accessService.getById(this.accessId)) as TencentAccess;
|
||||
const client = this.getClient(accessProvider, this.region);
|
||||
|
|
|
@ -1,121 +1,117 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin, utils } from "@certd/pipeline";
|
||||
import { Autowire, IAccessService, IsTaskPlugin, ITaskPlugin, RunStrategy, TaskInput, utils } from "@certd/pipeline";
|
||||
import tencentcloud from "tencentcloud-sdk-nodejs/index";
|
||||
import { K8sClient } from "@certd/plugin-util";
|
||||
import dayjs from "dayjs";
|
||||
import { Logger } from "log4js";
|
||||
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "DeployCertToTencentTKEIngress",
|
||||
title: "部署到腾讯云TKE-ingress",
|
||||
desc: "需要【上传到腾讯云】作为前置任务",
|
||||
input: {
|
||||
region: {
|
||||
title: "大区",
|
||||
value: "ap-guangzhou",
|
||||
required: true,
|
||||
},
|
||||
clusterId: {
|
||||
title: "集群ID",
|
||||
required: true,
|
||||
desc: "例如:cls-6lbj1vee",
|
||||
request: true,
|
||||
},
|
||||
namespace: {
|
||||
title: "集群namespace",
|
||||
value: "default",
|
||||
required: true,
|
||||
},
|
||||
secreteName: {
|
||||
title: "证书的secret名称",
|
||||
required: true,
|
||||
},
|
||||
ingressName: {
|
||||
title: "ingress名称",
|
||||
required: true,
|
||||
},
|
||||
ingressClass: {
|
||||
title: "ingress类型",
|
||||
component: {
|
||||
name: "a-select",
|
||||
options: [{ value: "qcloud" }, { value: "nginx" }],
|
||||
},
|
||||
helper: "可选 qcloud / nginx",
|
||||
},
|
||||
clusterIp: {
|
||||
title: "集群内网ip",
|
||||
helper: "如果开启了外网的话,无需设置",
|
||||
},
|
||||
clusterDomain: {
|
||||
title: "集群域名",
|
||||
helper: "可不填,默认为:[clusterId].ccs.tencent-cloud.com",
|
||||
},
|
||||
|
||||
tencentCertId: {
|
||||
title: "腾讯云证书id",
|
||||
helper: "请选择“上传证书到腾讯云”前置任务的输出",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
from: "UploadCertToTencent",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* AccessProvider的key,或者一个包含access的具体的对象
|
||||
*/
|
||||
accessId: {
|
||||
title: "Access授权",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
cert: {
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@IsTaskPlugin({
|
||||
name: "DeployCertToTencentTKEIngress",
|
||||
title: "部署到腾讯云TKE-ingress",
|
||||
desc: "需要【上传到腾讯云】作为前置任务",
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
},
|
||||
output: {},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class DeployCertToTencentTKEIngressPlugin extends AbstractPlugin implements TaskPlugin {
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
const { accessId, region, clusterId, clusterIp, ingressClass } = input;
|
||||
let { clusterDomain } = input;
|
||||
const accessProvider = this.accessService.getById(accessId);
|
||||
const tkeClient = this.getTkeClient(accessProvider, region);
|
||||
const kubeConfigStr = await this.getTkeKubeConfig(tkeClient, clusterId);
|
||||
export class DeployCertToTencentTKEIngressPlugin implements ITaskPlugin {
|
||||
@TaskInput({ title: "大区", value: "ap-guangzhou", required: true })
|
||||
region!: string;
|
||||
|
||||
@TaskInput({ title: "集群ID", required: true, desc: "例如:cls-6lbj1vee", request: true })
|
||||
clusterId!: string;
|
||||
|
||||
@TaskInput({ title: "集群namespace", value: "default", required: true })
|
||||
namespace!: string;
|
||||
|
||||
@TaskInput({ title: "证书的secret名称", required: true })
|
||||
secretName!: string | string[];
|
||||
|
||||
@TaskInput({ title: "ingress名称", required: true })
|
||||
ingressName!: string | string[];
|
||||
|
||||
@TaskInput({
|
||||
title: "ingress类型",
|
||||
component: {
|
||||
name: "a-select",
|
||||
options: [{ value: "qcloud" }, { value: "nginx" }],
|
||||
},
|
||||
helper: "可选 qcloud / nginx",
|
||||
})
|
||||
ingressClass!: string;
|
||||
|
||||
@TaskInput({ title: "集群内网ip", helper: "如果开启了外网的话,无需设置" })
|
||||
clusterIp!: string;
|
||||
|
||||
@TaskInput({ title: "集群域名", helper: "可不填,默认为:[clusterId].ccs.tencent-cloud.com" })
|
||||
clusterDomain!: string;
|
||||
@TaskInput({
|
||||
title: "腾讯云证书id",
|
||||
helper: "请选择“上传证书到腾讯云”前置任务的输出",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
from: "UploadCertToTencent",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
tencentCertId!: string;
|
||||
|
||||
/**
|
||||
* AccessProvider的key,或者一个包含access的具体的对象
|
||||
*/
|
||||
@TaskInput({
|
||||
title: "Access授权",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: any;
|
||||
|
||||
@Autowire()
|
||||
logger!: Logger;
|
||||
|
||||
@Autowire()
|
||||
accessService!: IAccessService;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
async onInit() {}
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const accessProvider = this.accessService.getById(this.accessId);
|
||||
const tkeClient = this.getTkeClient(accessProvider, this.region);
|
||||
const kubeConfigStr = await this.getTkeKubeConfig(tkeClient, this.clusterId);
|
||||
|
||||
this.logger.info("kubeconfig已成功获取");
|
||||
const k8sClient = new K8sClient(kubeConfigStr);
|
||||
if (clusterIp != null) {
|
||||
if (!clusterDomain) {
|
||||
clusterDomain = `${clusterId}.ccs.tencent-cloud.com`;
|
||||
if (this.clusterIp != null) {
|
||||
if (!this.clusterDomain) {
|
||||
this.clusterDomain = `${this.clusterId}.ccs.tencent-cloud.com`;
|
||||
}
|
||||
// 修改内网解析ip地址
|
||||
k8sClient.setLookup({ [clusterDomain]: { ip: clusterIp } });
|
||||
k8sClient.setLookup({ [this.clusterDomain]: { ip: this.clusterIp } });
|
||||
}
|
||||
const ingressType = ingressClass || "qcloud";
|
||||
const ingressType = this.ingressClass || "qcloud";
|
||||
if (ingressType === "qcloud") {
|
||||
await this.patchQcloudCertSecret({ k8sClient, input });
|
||||
await this.patchQcloudCertSecret({ k8sClient });
|
||||
} else {
|
||||
await this.patchNginxCertSecret({ k8sClient, input });
|
||||
await this.patchNginxCertSecret({ k8sClient });
|
||||
}
|
||||
|
||||
await utils.sleep(2000); // 停留2秒,等待secret部署完成
|
||||
await this.restartIngress({ k8sClient, input });
|
||||
return {};
|
||||
await this.restartIngress({ k8sClient });
|
||||
}
|
||||
|
||||
getTkeClient(accessProvider: any, region = "ap-guangzhou") {
|
||||
|
@ -154,15 +150,14 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractPlugin implemen
|
|||
return name + "-" + dayjs().format("YYYYMMDD-HHmmss");
|
||||
}
|
||||
|
||||
async patchQcloudCertSecret(options: { k8sClient: any; input: TaskInput }) {
|
||||
const { tencentCertId } = options.input;
|
||||
if (tencentCertId == null) {
|
||||
async patchQcloudCertSecret(options: { k8sClient: any }) {
|
||||
if (this.tencentCertId == null) {
|
||||
throw new Error("请先将【上传证书到腾讯云】作为前置任务");
|
||||
}
|
||||
this.logger.info("腾讯云证书ID:", tencentCertId);
|
||||
const certIdBase64 = Buffer.from(tencentCertId).toString("base64");
|
||||
this.logger.info("腾讯云证书ID:", this.tencentCertId);
|
||||
const certIdBase64 = Buffer.from(this.tencentCertId).toString("base64");
|
||||
|
||||
const { namespace, secretName } = options.input;
|
||||
const { namespace, secretName } = this;
|
||||
|
||||
const body = {
|
||||
data: {
|
||||
|
@ -174,7 +169,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractPlugin implemen
|
|||
},
|
||||
},
|
||||
};
|
||||
let secretNames = secretName;
|
||||
let secretNames: any = secretName;
|
||||
if (typeof secretName === "string") {
|
||||
secretNames = [secretName];
|
||||
}
|
||||
|
@ -184,15 +179,15 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractPlugin implemen
|
|||
}
|
||||
}
|
||||
|
||||
async patchNginxCertSecret(options: { k8sClient: any; input: TaskInput }) {
|
||||
const { k8sClient, input } = options;
|
||||
const { cert } = input;
|
||||
async patchNginxCertSecret(options: { k8sClient: any }) {
|
||||
const { k8sClient } = options;
|
||||
const { cert } = this;
|
||||
const crt = cert.crt;
|
||||
const key = cert.key;
|
||||
const crtBase64 = Buffer.from(crt).toString("base64");
|
||||
const keyBase64 = Buffer.from(key).toString("base64");
|
||||
|
||||
const { namespace, secretName } = input;
|
||||
const { namespace, secretName } = this;
|
||||
|
||||
const body = {
|
||||
data: {
|
||||
|
@ -215,9 +210,9 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractPlugin implemen
|
|||
}
|
||||
}
|
||||
|
||||
async restartIngress(options: { k8sClient: any; input: TaskInput }) {
|
||||
const { k8sClient, input } = options;
|
||||
const { namespace, ingressName } = input;
|
||||
async restartIngress(options: { k8sClient: any }) {
|
||||
const { k8sClient } = options;
|
||||
const { namespace, ingressName } = this;
|
||||
|
||||
const body = {
|
||||
metadata: {
|
||||
|
@ -226,7 +221,7 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractPlugin implemen
|
|||
},
|
||||
},
|
||||
};
|
||||
let ingressNames = ingressName;
|
||||
let ingressNames = this.ingressName;
|
||||
if (typeof ingressName === "string") {
|
||||
ingressNames = [ingressName];
|
||||
}
|
||||
|
|
|
@ -1,49 +1,58 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin } from "@certd/pipeline";
|
||||
import { Autowire, IAccessService, IsTaskPlugin, ITaskPlugin, RunStrategy, TaskInput, TaskOutput, LOGGER } from "@certd/pipeline";
|
||||
import tencentcloud from "tencentcloud-sdk-nodejs/index";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "UploadCertToTencent",
|
||||
title: "上传证书到腾讯云",
|
||||
desc: "上传成功后输出:tencentCertId",
|
||||
input: {
|
||||
name: {
|
||||
title: "证书名称",
|
||||
},
|
||||
accessId: {
|
||||
title: "Access授权",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
cert: {
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@IsTaskPlugin({
|
||||
name: "UploadCertToTencent",
|
||||
title: "上传证书到腾讯云",
|
||||
desc: "上传成功后输出:tencentCertId",
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
},
|
||||
output: {
|
||||
tencentCertId: {
|
||||
title: "上传成功后的腾讯云CertId",
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class UploadToTencentPlugin extends AbstractPlugin implements TaskPlugin {
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
const { accessId, name, cert } = input;
|
||||
export class UploadToTencentPlugin implements ITaskPlugin {
|
||||
@TaskInput({ title: "证书名称" })
|
||||
name!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "Access授权",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: any;
|
||||
|
||||
@TaskOutput({
|
||||
title: "上传成功后的腾讯云CertId",
|
||||
})
|
||||
tencentCertId?: string;
|
||||
|
||||
@Autowire()
|
||||
accessService!: IAccessService;
|
||||
|
||||
@Autowire()
|
||||
logger!: LOGGER;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
async onInit() {}
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const { accessId, name, cert } = this;
|
||||
const accessProvider = this.accessService.getById(accessId);
|
||||
const certName = this.appendTimeSuffix(name || cert.domain);
|
||||
const client = this.getClient(accessProvider);
|
||||
|
@ -56,7 +65,8 @@ export class UploadToTencentPlugin extends AbstractPlugin implements TaskPlugin
|
|||
const ret = await client.UploadCertificate(params);
|
||||
this.checkRet(ret);
|
||||
this.logger.info("证书上传成功:tencentCertId=", ret.CertificateId);
|
||||
return { tencentCertId: ret.CertificateId };
|
||||
|
||||
this.tencentCertId = ret.CertificateId;
|
||||
}
|
||||
|
||||
appendTimeSuffix(name: string) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"kubernetes-client": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"log4js": "^6.7.1",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"vue-tsc": "^0.38.9",
|
||||
"@alicloud/cs20151215": "^3.0.3",
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f508b6426b5869ae0fd33d8ec8e170e097eed9d4
|
||||
Subproject commit 08f08022903aed6ba5150a80ea3484a8bc1830b7
|
Loading…
Reference in New Issue