mirror of https://github.com/certd/certd
refactor: pipeline edit view
parent
370a28c10e
commit
e1466737e3
|
@ -15,7 +15,7 @@
|
|||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"no-unused-expressions": "off",
|
||||
// "no-unused-expressions": "off",
|
||||
"max-len": [0, 160, 2, { "ignoreUrls": true }]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"private": true,
|
||||
"version": "0.3.0",
|
||||
"main": "./dist/pipeline.umd.js",
|
||||
"module": "./dist/fast-crud.mjs",
|
||||
"module": "./dist/pipeline.mjs",
|
||||
"types": "./dist/es/index.d.ts",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
@ -19,6 +19,7 @@
|
|||
"node-forge": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vue-tsc": "^0.38.9",
|
||||
"@alicloud/cs20151215": "^3.0.3",
|
||||
"@alicloud/openapi-client": "^0.4.0",
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { AbstractRegistrable } from "../registry";
|
||||
import { AccessDefine } from "./api";
|
||||
|
||||
export abstract class AbstractAccess extends AbstractRegistrable {}
|
||||
export abstract class AbstractAccess extends AbstractRegistrable<AccessDefine> {}
|
||||
|
|
|
@ -8,6 +8,6 @@ export type AccessDefine = Registrable & {
|
|||
};
|
||||
export function IsAccess(define: AccessDefine) {
|
||||
return function (target: any) {
|
||||
target.define = define;
|
||||
target.prototype.define = define;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IStorage } from "./storage";
|
||||
import { IStorage, MemoryStorage } from "./storage";
|
||||
|
||||
export interface IContext {
|
||||
get(key: string): Promise<any>;
|
||||
|
@ -7,14 +7,20 @@ export interface IContext {
|
|||
|
||||
export class ContextFactory {
|
||||
storage: IStorage;
|
||||
memoryStorage: IStorage;
|
||||
|
||||
constructor(storage: IStorage) {
|
||||
this.storage = storage;
|
||||
this.memoryStorage = new MemoryStorage();
|
||||
}
|
||||
|
||||
getContext(scope: string, namespace: string): IContext {
|
||||
return new StorageContext(scope, namespace, this.storage);
|
||||
}
|
||||
|
||||
getMemoryContext(scope: string, namespace: string): IContext {
|
||||
return new StorageContext(scope, namespace, this.memoryStorage);
|
||||
}
|
||||
}
|
||||
|
||||
export class StorageContext implements IContext {
|
||||
|
|
|
@ -3,10 +3,9 @@ import _ from "lodash";
|
|||
import { RunHistory } from "./run-history";
|
||||
import { pluginRegistry, TaskPlugin } from "../plugin";
|
||||
import { IAccessService } from "../access/access-service";
|
||||
import { ContextFactory, StorageContext } from "./context";
|
||||
import { IStorage, MemoryStorage } from "./storage";
|
||||
import { ContextFactory } from "./context";
|
||||
import { IStorage } from "./storage";
|
||||
import { logger } from "../utils/util.log";
|
||||
import { use } from "chai";
|
||||
|
||||
export class Executor {
|
||||
userId: any;
|
||||
|
@ -16,7 +15,14 @@ export class Executor {
|
|||
accessService: IAccessService;
|
||||
contextFactory: ContextFactory;
|
||||
onChanged: (history: RunHistory) => void;
|
||||
constructor(options: { userId: any; pipeline: Pipeline; storage: IStorage; onChanged: (history: RunHistory) => void; lastSuccessHistory?: RunHistory; accessService: IAccessService }) {
|
||||
constructor(options: {
|
||||
userId: any;
|
||||
pipeline: Pipeline;
|
||||
storage: IStorage;
|
||||
onChanged: (history: RunHistory) => void;
|
||||
lastSuccessHistory?: RunHistory;
|
||||
accessService: IAccessService;
|
||||
}) {
|
||||
this.pipeline = options.pipeline;
|
||||
this.lastSuccessHistory = options.lastSuccessHistory ?? new RunHistory();
|
||||
this.onChanged = options.onChanged;
|
||||
|
@ -82,13 +88,29 @@ export class Executor {
|
|||
private async runStep(step: Step) {
|
||||
//执行任务
|
||||
const taskPlugin: TaskPlugin = await this.getPlugin(step.type);
|
||||
|
||||
const define = taskPlugin.getDefine();
|
||||
//从outputContext读取输入参数
|
||||
_.forEach(define.input, (item, key) => {
|
||||
if (item.component?.name === "output-selector") {
|
||||
const contextKey = step.input[key];
|
||||
if (contextKey != null) {
|
||||
step.input[key] = this.runtime.context[contextKey];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const res = await taskPlugin.execute(step.input);
|
||||
_.merge(this.runtime.context, res);
|
||||
|
||||
//输出到output context
|
||||
_.forEach(define.output, (item, key) => {
|
||||
const contextKey = `step.${step.id}.${key}`;
|
||||
this.runtime.context[contextKey] = res[key];
|
||||
});
|
||||
}
|
||||
|
||||
private async getPlugin(type: string): Promise<TaskPlugin> {
|
||||
const pluginClass = pluginRegistry.get(type);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const plugin = new pluginClass();
|
||||
await plugin.doInit({
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
import { AbstractRegistrable } from "../registry";
|
||||
import {
|
||||
CreateRecordOptions,
|
||||
IDnsProvider,
|
||||
DnsProviderDefine,
|
||||
RemoveRecordOptions,
|
||||
} from "./api";
|
||||
import { CreateRecordOptions, IDnsProvider, DnsProviderDefine, RemoveRecordOptions } from "./api";
|
||||
import { AbstractAccess } from "../access";
|
||||
export abstract class AbstractDnsProvider
|
||||
extends AbstractRegistrable
|
||||
implements IDnsProvider
|
||||
{
|
||||
static define: DnsProviderDefine;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
export abstract class AbstractDnsProvider extends AbstractRegistrable<DnsProviderDefine> implements IDnsProvider {
|
||||
// @ts-ignore
|
||||
access: AbstractAccess;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ export type RemoveRecordOptions = CreateRecordOptions & {
|
|||
};
|
||||
|
||||
export interface IDnsProvider {
|
||||
getDefine(): DnsProviderDefine;
|
||||
createRecord(options: CreateRecordOptions): Promise<any>;
|
||||
|
||||
removeRecord(options: RemoveRecordOptions): Promise<any>;
|
||||
|
@ -22,7 +23,7 @@ export interface IDnsProvider {
|
|||
|
||||
export function IsDnsProvider(define: DnsProviderDefine) {
|
||||
return function (target: any) {
|
||||
target.define = define;
|
||||
target.prototype.define = define;
|
||||
dnsProviderRegistry.install(target);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
import { AbstractDnsProvider } from "../abstract-dns-provider";
|
||||
import Core from "@alicloud/pop-core";
|
||||
import _ from "lodash";
|
||||
import {
|
||||
CreateRecordOptions,
|
||||
IDnsProvider,
|
||||
IsDnsProvider,
|
||||
RemoveRecordOptions,
|
||||
} from "../api";
|
||||
import { CreateRecordOptions, IDnsProvider, IsDnsProvider, RemoveRecordOptions } from "../api";
|
||||
|
||||
@IsDnsProvider({
|
||||
name: "aliyun",
|
||||
|
@ -14,10 +9,7 @@ import {
|
|||
desc: "阿里云DNS解析提供商",
|
||||
accessType: "aliyun",
|
||||
})
|
||||
export class AliyunDnsProvider
|
||||
extends AbstractDnsProvider
|
||||
implements IDnsProvider
|
||||
{
|
||||
export class AliyunDnsProvider extends AbstractDnsProvider implements IDnsProvider {
|
||||
client: any;
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -42,11 +34,7 @@ export class AliyunDnsProvider
|
|||
method: "POST",
|
||||
};
|
||||
|
||||
const ret = await this.client.request(
|
||||
"DescribeDomains",
|
||||
params,
|
||||
requestOption
|
||||
);
|
||||
const ret = await this.client.request("DescribeDomains", params, requestOption);
|
||||
return ret.Domains.Domain;
|
||||
}
|
||||
|
||||
|
@ -80,11 +68,7 @@ export class AliyunDnsProvider
|
|||
method: "POST",
|
||||
};
|
||||
|
||||
const ret = await this.client.request(
|
||||
"DescribeDomainRecords",
|
||||
params,
|
||||
requestOption
|
||||
);
|
||||
const ret = await this.client.request("DescribeDomainRecords", params, requestOption);
|
||||
return ret.DomainRecords.Record;
|
||||
}
|
||||
|
||||
|
@ -108,11 +92,7 @@ export class AliyunDnsProvider
|
|||
};
|
||||
|
||||
try {
|
||||
const ret = await this.client.request(
|
||||
"AddDomainRecord",
|
||||
params,
|
||||
requestOption
|
||||
);
|
||||
const ret = await this.client.request("AddDomainRecord", params, requestOption);
|
||||
this.logger.info("添加域名解析成功:", value, value, ret.RecordId);
|
||||
return ret.RecordId;
|
||||
} catch (e: any) {
|
||||
|
@ -124,7 +104,7 @@ export class AliyunDnsProvider
|
|||
}
|
||||
}
|
||||
async removeRecord(options: RemoveRecordOptions): Promise<any> {
|
||||
const { fullRecord, value, type, record } = options;
|
||||
const { fullRecord, value, record } = options;
|
||||
const params = {
|
||||
RegionId: "cn-hangzhou",
|
||||
RecordId: record,
|
||||
|
@ -134,11 +114,7 @@ export class AliyunDnsProvider
|
|||
method: "POST",
|
||||
};
|
||||
|
||||
const ret = await this.client.request(
|
||||
"DeleteDomainRecord",
|
||||
params,
|
||||
requestOption
|
||||
);
|
||||
const ret = await this.client.request("DeleteDomainRecord", params, requestOption);
|
||||
this.logger.info("删除域名解析成功:", fullRecord, value, ret.RecordId);
|
||||
return ret.RecordId;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Registry } from "../registry";
|
||||
import { AbstractDnsProvider } from "./abstract-dns-provider";
|
||||
|
||||
// @ts-ignore
|
||||
export const dnsProviderRegistry = new Registry<typeof AbstractDnsProvider>();
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { AbstractRegistrable } from "../registry";
|
||||
import { PluginDefine } from "./api";
|
||||
import { Logger } from "log4js";
|
||||
import { logger } from "../utils/util.log";
|
||||
import { IAccessService } from "../access/access-service";
|
||||
import { IContext } from "../core/context";
|
||||
import { PluginDefine, TaskInput, TaskOutput, TaskPlugin } from "./api";
|
||||
|
||||
export abstract class AbstractPlugin extends AbstractRegistrable {
|
||||
static define: PluginDefine;
|
||||
export abstract class AbstractPlugin extends AbstractRegistrable<PluginDefine> implements TaskPlugin {
|
||||
logger: Logger = logger;
|
||||
// @ts-ignore
|
||||
accessService: IAccessService;
|
||||
|
@ -25,4 +24,6 @@ export abstract class AbstractPlugin extends AbstractRegistrable {
|
|||
protected async onInit(): Promise<void> {
|
||||
//
|
||||
}
|
||||
|
||||
abstract execute(input: TaskInput): Promise<TaskOutput>;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ export type Storage = {
|
|||
|
||||
export type TaskOutputDefine = {
|
||||
title: string;
|
||||
key: string;
|
||||
value?: any;
|
||||
storage?: Storage;
|
||||
};
|
||||
|
@ -38,6 +37,7 @@ export type PluginDefine = Registrable & {
|
|||
};
|
||||
|
||||
export interface TaskPlugin {
|
||||
getDefine(): PluginDefine;
|
||||
execute(input: TaskInput): Promise<TaskOutput>;
|
||||
}
|
||||
|
||||
|
@ -50,9 +50,9 @@ export type OutputVO = {
|
|||
export function IsTask(define: (() => PluginDefine) | PluginDefine) {
|
||||
return function (target: any) {
|
||||
if (define instanceof Function) {
|
||||
target.define = define();
|
||||
target.prototype.define = define();
|
||||
} else {
|
||||
target.define = define;
|
||||
target.prototype.define = define;
|
||||
}
|
||||
|
||||
pluginRegistry.install(target);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// @ts-ignore
|
||||
import acme, { Authorization } from "@certd/acme-client";
|
||||
import * as acme from "@certd/acme-client";
|
||||
import _ from "lodash";
|
||||
import { logger } from "../../../utils/util.log";
|
||||
import { AbstractDnsProvider } from "../../../dns-provider/abstract-dns-provider";
|
||||
import { IContext } from "../../../core/context";
|
||||
import { IDnsProvider } from "../../../dns-provider";
|
||||
import { Challenge } from "@certd/acme-client/types/rfc8555";
|
||||
|
||||
console.log("acme", acme);
|
||||
export class AcmeService {
|
||||
userContext: IContext;
|
||||
constructor(options: { userContext: IContext }) {
|
||||
|
@ -155,10 +155,10 @@ export class AcmeService {
|
|||
email: email,
|
||||
termsOfServiceAgreed: true,
|
||||
challengePriority: ["dns-01"],
|
||||
challengeCreateFn: async (authz: Authorization, challenge: Challenge, keyAuthorization: string): Promise<any> => {
|
||||
challengeCreateFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string): Promise<any> => {
|
||||
return await this.challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider);
|
||||
},
|
||||
challengeRemoveFn: async (authz: Authorization, challenge: Challenge, keyAuthorization: string, recordItem: any): Promise<any> => {
|
||||
challengeRemoveFn: async (authz: acme.Authorization, challenge: Challenge, keyAuthorization: string, recordItem: any): Promise<any> => {
|
||||
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ export type CertInfo = {
|
|||
title: "证书申请",
|
||||
input: {
|
||||
domains: {
|
||||
title: "域名",
|
||||
component: {
|
||||
name: "a-select",
|
||||
vModel: "value",
|
||||
|
@ -28,6 +29,7 @@ export type CertInfo = {
|
|||
helper: "请输入域名",
|
||||
},
|
||||
email: {
|
||||
title: "邮箱",
|
||||
component: {
|
||||
name: "a-input",
|
||||
vModel: "value",
|
||||
|
@ -35,12 +37,14 @@ export type CertInfo = {
|
|||
helper: "请输入邮箱",
|
||||
},
|
||||
dnsProviderType: {
|
||||
title: "DNS提供商",
|
||||
component: {
|
||||
name: "a-select",
|
||||
},
|
||||
helper: "请选择dns解析提供商",
|
||||
},
|
||||
dnsProviderAccess: {
|
||||
title: "DNS解析授权",
|
||||
component: {
|
||||
name: "access-selector",
|
||||
},
|
||||
|
@ -49,7 +53,7 @@ export type CertInfo = {
|
|||
renewDays: {
|
||||
title: "更新天数",
|
||||
component: {
|
||||
name: "a-number",
|
||||
name: "a-input-number",
|
||||
value: 20,
|
||||
},
|
||||
helper: "到期前多少天后更新证书",
|
||||
|
|
|
@ -69,18 +69,17 @@ export class DeployCertToAliyunCDN extends AbstractPlugin implements TaskPlugin
|
|||
}
|
||||
|
||||
async buildParams(input: TaskInput) {
|
||||
const { certName, domainName, cert } = input;
|
||||
const { certName, domainName } = input;
|
||||
const CertName = certName + "-" + dayjs().format("YYYYMMDDHHmmss");
|
||||
|
||||
const newCert = (await this.pipelineContext.get(cert)) as CertInfo;
|
||||
const cert = input.cert as CertInfo;
|
||||
return {
|
||||
RegionId: "cn-hangzhou",
|
||||
DomainName: domainName,
|
||||
ServerCertificateStatus: "on",
|
||||
CertName: CertName,
|
||||
CertType: "upload",
|
||||
ServerCertificate: newCert.crt,
|
||||
PrivateKey: newCert.key,
|
||||
ServerCertificate: cert.crt,
|
||||
PrivateKey: cert.key,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -95,7 +94,7 @@ export class DeployCertToAliyunCDN extends AbstractPlugin implements TaskPlugin
|
|||
|
||||
checkRet(ret: any) {
|
||||
if (ret.code != null) {
|
||||
throw new Error("执行失败:", ret.Message);
|
||||
throw new Error("执行失败:" + ret.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { IsTask, TaskInput, TaskOutput, TaskPlugin } from "../api";
|
|||
title: "测试插件回声",
|
||||
input: {
|
||||
cert: {
|
||||
title: "cert",
|
||||
component: {
|
||||
name: "output-selector",
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Registry } from "../registry";
|
||||
import { AbstractPlugin } from "./abstract-plugin";
|
||||
|
||||
// @ts-ignore
|
||||
export const pluginRegistry = new Registry<typeof AbstractPlugin>();
|
||||
|
|
|
@ -7,9 +7,14 @@ export type Registrable = {
|
|||
desc?: string;
|
||||
};
|
||||
|
||||
export abstract class AbstractRegistrable {
|
||||
static define: Registrable;
|
||||
export abstract class AbstractRegistrable<T extends Registrable> {
|
||||
logger: Logger = logger;
|
||||
// @ts-ignore
|
||||
define: T;
|
||||
|
||||
getDefine(): T {
|
||||
return this.define;
|
||||
}
|
||||
}
|
||||
export class Registry<T extends typeof AbstractRegistrable> {
|
||||
storage: {
|
||||
|
@ -20,7 +25,9 @@ export class Registry<T extends typeof AbstractRegistrable> {
|
|||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
let defineName = target.define.name;
|
||||
// @ts-ignore
|
||||
const define = new target().define;
|
||||
let defineName = define.name;
|
||||
if (defineName == null) {
|
||||
defineName = target.name;
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
export interface ServiceContext {
|
||||
get(name: string): any;
|
||||
register(name: string, service: any): void;
|
||||
}
|
||||
|
||||
export class ServiceContextImpl implements ServiceContext {
|
||||
register(name: string, service: any): void {}
|
||||
storage: {
|
||||
[key: string]: any;
|
||||
} = {};
|
||||
get(name: string): any {
|
||||
return this.storage[name];
|
||||
}
|
||||
}
|
||||
|
||||
export const serviceContext = new ServiceContextImpl();
|
|
@ -3,8 +3,9 @@ import "mocha";
|
|||
import { EchoPlugin } from "../src/plugin/plugins";
|
||||
describe("task_plugin", function () {
|
||||
it("#taskplugin", function () {
|
||||
const define = EchoPlugin.define;
|
||||
new EchoPlugin().execute({ context: {}, props: { test: 111 } });
|
||||
const echoPlugin = new EchoPlugin();
|
||||
const define = echoPlugin.define;
|
||||
echoPlugin.execute({ context: {}, props: { test: 111 } });
|
||||
expect(define.name).eq("EchoPlugin");
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue