mirror of https://github.com/certd/certd
refactor: decorator
parent
c23f6172b5
commit
717d203622
|
@ -12,22 +12,29 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^0.3.0",
|
||||
"axios": "^0.21.1",
|
||||
"dayjs": "^1.11.6",
|
||||
"lodash": "^4.17.21",
|
||||
"node-forge": "^0.10.0",
|
||||
"log4js": "^6.3.0",
|
||||
"axios": "^0.21.1",
|
||||
"node-forge": "^0.10.0",
|
||||
"qs": "^6.9.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.14.186",
|
||||
"vue-tsc": "^0.38.9",
|
||||
"@alicloud/cs20151215": "^3.0.3",
|
||||
"@alicloud/openapi-client": "^0.4.0",
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@midwayjs/bootstrap": "^3.9.1",
|
||||
"@midwayjs/cache": "^3.9.0",
|
||||
"@midwayjs/cli": "^1.3.21",
|
||||
"@midwayjs/core": "^3.0.0",
|
||||
"@midwayjs/decorator": "^3.0.0",
|
||||
"@midwayjs/koa": "^3.9.0",
|
||||
"@midwayjs/logger": "^2.17.0",
|
||||
"@midwayjs/typeorm": "^3.9.0",
|
||||
"@midwayjs/validate": "^3.9.0",
|
||||
"@types/chai": "^4.3.3",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node-forge": "^1.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||
|
@ -41,6 +48,7 @@
|
|||
"mocha": "^10.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.8.4",
|
||||
"vite": "^3.1.0"
|
||||
"vite": "^3.1.0",
|
||||
"vue-tsc": "^0.38.9"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
import { AbstractRegistrable } from "../registry";
|
||||
import { AccessDefine } from "./api";
|
||||
|
||||
export abstract class AbstractAccess extends AbstractRegistrable<AccessDefine> {}
|
|
@ -3,22 +3,15 @@ import { accessRegistry } from "./registry";
|
|||
import { FormItemProps } from "../d.ts";
|
||||
import { AbstractAccess } from "./abstract-access";
|
||||
|
||||
export type AccessInput = FormItemProps & {
|
||||
export type AccessInputDefine = FormItemProps & {
|
||||
title: string;
|
||||
required?: boolean;
|
||||
};
|
||||
export type AccessDefine = Registrable & {
|
||||
input: {
|
||||
[key: string]: AccessInput;
|
||||
inputs?: {
|
||||
[key: string]: AccessInputDefine;
|
||||
};
|
||||
};
|
||||
export function IsAccess(define: AccessDefine) {
|
||||
return function (target: any) {
|
||||
target.prototype.define = define;
|
||||
accessRegistry.install(target);
|
||||
};
|
||||
}
|
||||
|
||||
export interface IAccessService {
|
||||
getById(id: any): Promise<AbstractAccess>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// src/decorator/memoryCache.decorator.ts
|
||||
import {
|
||||
attachClassMetadata,
|
||||
attachPropertyDataToClass,
|
||||
getClassMetadata,
|
||||
listModule,
|
||||
listPropertyDataFromClass,
|
||||
saveClassMetadata,
|
||||
saveModule,
|
||||
} from "@midwayjs/decorator";
|
||||
import { AccessDefine, AccessInputDefine } from "./api";
|
||||
import _ from "lodash-es";
|
||||
import { accessRegistry } from "./registry";
|
||||
|
||||
// 提供一个唯一 key
|
||||
export const ACCESS_CLASS_KEY = "decorator:access";
|
||||
|
||||
export function IsAccess(define: AccessDefine): ClassDecorator {
|
||||
console.log("is access define:", define);
|
||||
return (target: any) => {
|
||||
console.log("is access load:", target);
|
||||
// 将装饰的类,绑定到该装饰器,用于后续能获取到 class
|
||||
saveModule(ACCESS_CLASS_KEY, target);
|
||||
// 保存一些元数据信息,任意你希望存的东西
|
||||
saveClassMetadata(
|
||||
ACCESS_CLASS_KEY,
|
||||
{
|
||||
define,
|
||||
},
|
||||
target
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const ACCESS_INPUT_KEY = "decorator:access:input";
|
||||
|
||||
export function IsAccessInput(input?: AccessInputDefine): PropertyDecorator {
|
||||
return (target, propertyKey) => {
|
||||
attachPropertyDataToClass(ACCESS_INPUT_KEY, { input }, target, propertyKey, propertyKey as string);
|
||||
|
||||
attachClassMetadata(
|
||||
ACCESS_CLASS_KEY,
|
||||
{
|
||||
inputs: {
|
||||
[propertyKey]: input,
|
||||
},
|
||||
},
|
||||
target
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function registerAccess() {
|
||||
const modules = listModule(ACCESS_CLASS_KEY);
|
||||
for (const mod of modules) {
|
||||
console.log("mod", mod);
|
||||
const define = getClassMetadata(ACCESS_CLASS_KEY, mod);
|
||||
console.log("define", define);
|
||||
const inputs = listPropertyDataFromClass(ACCESS_INPUT_KEY, mod);
|
||||
console.log("inputs", inputs);
|
||||
for (const input of inputs) {
|
||||
define.inputs = {};
|
||||
_.merge(define.inputs, input.inputs);
|
||||
}
|
||||
|
||||
accessRegistry.register(define.name, {
|
||||
define,
|
||||
target: mod,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
export * from "./api";
|
||||
export * from "./abstract-access";
|
||||
export * from "./registry";
|
||||
export * from "./decorator";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Registry } from "../registry";
|
||||
import { AbstractAccess } from "./abstract-access";
|
||||
|
||||
// @ts-ignore
|
||||
export const accessRegistry = new Registry<typeof AbstractAccess>();
|
||||
export const accessRegistry = new Registry();
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { AxiosInstance } from "axios";
|
||||
import { IContext } from "../core";
|
||||
|
||||
export type HttpClient = AxiosInstance;
|
||||
export type UserContext = IContext;
|
||||
export type PipelineContext = IContext;
|
|
@ -1,13 +1,14 @@
|
|||
import { ConcurrencyStrategy, Pipeline, ResultType, Runnable, RunStrategy, Stage, Step, Task } from "../d.ts";
|
||||
import _ from "lodash";
|
||||
import { RunHistory } from "./run-history";
|
||||
import { pluginRegistry, TaskPlugin } from "../plugin";
|
||||
import { pluginRegistry, ITaskPlugin, PluginDefine } 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";
|
||||
export class Executor {
|
||||
userId: any;
|
||||
pipeline: Pipeline;
|
||||
|
@ -134,40 +135,38 @@ export class Executor {
|
|||
|
||||
private async runStep(step: Step) {
|
||||
//执行任务
|
||||
const taskPlugin: TaskPlugin = await this.getPlugin(step.type, this.runtime.loggers[step.id]);
|
||||
const plugin: RegistryItem = pluginRegistry.get(step.type);
|
||||
const context = {
|
||||
logger: this.runtime.loggers[step.id],
|
||||
accessService: this.accessService,
|
||||
pipelineContext: this.pipelineContext,
|
||||
userContext: this.contextFactory.getContext("user", this.userId),
|
||||
http: request,
|
||||
};
|
||||
// @ts-ignore
|
||||
delete taskPlugin.define;
|
||||
const define = taskPlugin.getDefine();
|
||||
const instance = new plugin.target();
|
||||
// @ts-ignore
|
||||
const define: PluginDefine = plugin.define;
|
||||
//从outputContext读取输入参数
|
||||
_.forEach(define.input, (item, key) => {
|
||||
_.forEach(define.inputs, (item, key) => {
|
||||
if (item.component?.name === "pi-output-selector") {
|
||||
const contextKey = step.input[key];
|
||||
if (contextKey != null) {
|
||||
step.input[key] = this.runtime.context[contextKey];
|
||||
}
|
||||
} else {
|
||||
instance[key] = step.input[key];
|
||||
}
|
||||
});
|
||||
|
||||
const res = await taskPlugin.execute(step.input);
|
||||
|
||||
|
||||
const res = await instance.execute();
|
||||
|
||||
//输出到output context
|
||||
_.forEach(define.output, (item, key) => {
|
||||
_.forEach(define.outputs, (item, key) => {
|
||||
const contextKey = `step.${step.id}.${key}`;
|
||||
this.runtime.context[contextKey] = res[key];
|
||||
});
|
||||
}
|
||||
|
||||
private async getPlugin(type: string, logger: Logger): Promise<TaskPlugin> {
|
||||
const pluginClass = pluginRegistry.get(type);
|
||||
// @ts-ignore
|
||||
const plugin = new pluginClass();
|
||||
await plugin.doInit({
|
||||
accessService: this.accessService,
|
||||
pipelineContext: this.pipelineContext,
|
||||
userContext: this.contextFactory.getContext("user", this.userId),
|
||||
logger,
|
||||
http: request,
|
||||
});
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { Registrable } from "../registry";
|
||||
import { dnsProviderRegistry } from "./registry";
|
||||
import { AbstractDnsProvider } from "./abstract-dns-provider";
|
||||
|
||||
export type DnsProviderDefine = Registrable & {
|
||||
accessType: string;
|
||||
|
@ -16,19 +14,6 @@ export type RemoveRecordOptions = CreateRecordOptions & {
|
|||
};
|
||||
|
||||
export interface IDnsProvider {
|
||||
getDefine(): DnsProviderDefine;
|
||||
createRecord(options: CreateRecordOptions): Promise<any>;
|
||||
|
||||
removeRecord(options: RemoveRecordOptions): Promise<any>;
|
||||
}
|
||||
|
||||
export function IsDnsProvider(define: (() => DnsProviderDefine) | DnsProviderDefine) {
|
||||
return function (target: typeof AbstractDnsProvider) {
|
||||
if (define instanceof Function) {
|
||||
target.prototype.define = define();
|
||||
} else {
|
||||
target.prototype.define = define;
|
||||
}
|
||||
dnsProviderRegistry.install(target);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// 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 { dnsProviderRegistry } from "./registry";
|
||||
import { DnsProviderDefine } from "./api";
|
||||
|
||||
// 提供一个唯一 key
|
||||
export const DNS_PROVIDER_CLASS_KEY = "decorator:dnsProvider";
|
||||
|
||||
export function IsDnsProvider(define: DnsProviderDefine): ClassDecorator {
|
||||
console.log("is task plugin define:", define);
|
||||
return (target: any) => {
|
||||
console.log("is task plugin load:", target);
|
||||
// 将装饰的类,绑定到该装饰器,用于后续能获取到 class
|
||||
saveModule(DNS_PROVIDER_CLASS_KEY, target);
|
||||
// 保存一些元数据信息,任意你希望存的东西
|
||||
saveClassMetadata(
|
||||
DNS_PROVIDER_CLASS_KEY,
|
||||
{
|
||||
define,
|
||||
},
|
||||
target
|
||||
);
|
||||
// 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx
|
||||
Scope(ScopeEnum.Prototype)(target);
|
||||
|
||||
// 调用一下 Provide 装饰器,这样用户的 class 可以省略写 @Provide() 装饰器了
|
||||
Provide()(target);
|
||||
};
|
||||
}
|
||||
|
||||
export function registerDnsProviders() {
|
||||
const modules = listModule(DNS_PROVIDER_CLASS_KEY);
|
||||
for (const mod of modules) {
|
||||
console.log("mod", mod);
|
||||
const define = getClassMetadata(DNS_PROVIDER_CLASS_KEY, mod);
|
||||
console.log("define", define);
|
||||
dnsProviderRegistry.register(define.name, {
|
||||
define,
|
||||
target: mod,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
export * from "./api";
|
||||
export * from "./registry";
|
||||
export * from "./abstract-dns-provider";
|
||||
export * from "./decorator";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Registry } from "../registry";
|
||||
import { AbstractDnsProvider } from "./abstract-dns-provider";
|
||||
|
||||
// @ts-ignore
|
||||
export const dnsProviderRegistry = new Registry<typeof AbstractDnsProvider>();
|
||||
export const dnsProviderRegistry = new Registry();
|
||||
|
|
|
@ -5,3 +5,6 @@ export * from "./registry";
|
|||
export * from "./dns-provider";
|
||||
export * from "./plugin";
|
||||
export * from "./utils";
|
||||
export * from "./decorator";
|
||||
export * from "./midway";
|
||||
export * from "./context";
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import { Config, Configuration, getClassMetadata, Inject, listModule, listPropertyDataFromClass, Logger } from "@midwayjs/decorator";
|
||||
import _ from "lodash-es";
|
||||
// @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";
|
||||
|
||||
// ... (see below) ...
|
||||
@Configuration({
|
||||
namespace: "pipeline",
|
||||
//importConfigs: [join(__dirname, './config')],
|
||||
})
|
||||
export class PipelineConfiguration {
|
||||
@Config()
|
||||
// @ts-ignore
|
||||
config;
|
||||
@Logger()
|
||||
// @ts-ignore
|
||||
logger: ILogger;
|
||||
|
||||
@Inject()
|
||||
// @ts-ignore
|
||||
decoratorService: MidwayDecoratorService;
|
||||
|
||||
async onReady(container: IMidwayContainer) {
|
||||
this.logger.info("pipeline install");
|
||||
|
||||
registerPlugins();
|
||||
registerAccess();
|
||||
registerDnsProviders();
|
||||
//this.implPropertyDecorator(container);
|
||||
this.logger.info("pipeline installed");
|
||||
}
|
||||
|
||||
// implPropertyDecorator(container: IMidwayContainer) {
|
||||
// this.logger.info("初始化 property decorator");
|
||||
// // 实现装饰器
|
||||
// this.decoratorService.registerPropertyHandler(CLASS_INPUTS_KEY, (propertyName, meta) => {
|
||||
// return undefined;
|
||||
// });
|
||||
//
|
||||
// const autowireWhiteList: any = {
|
||||
// logger: true,
|
||||
// };
|
||||
// this.decoratorService.registerPropertyHandler(CLASS_AUTOWIRE_KEY, (propertyName, meta) => {
|
||||
// // eslint-disable-next-line no-debugger
|
||||
// debugger;
|
||||
// const className = meta.name;
|
||||
// if (autowireWhiteList[className]) {
|
||||
// //在白名单里面,注入
|
||||
// return container.get(className);
|
||||
// }
|
||||
// this.logger.warn(`autowire failed:${className} class is not in white list`);
|
||||
// return undefined;
|
||||
// });
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// src/index.ts
|
||||
export { PipelineConfiguration } from "./configuration";
|
||||
// export * from './controller/user';
|
||||
// export * from './controller/api';
|
||||
// export * from './service/user';
|
|
@ -1,13 +1,6 @@
|
|||
import { Registrable } from "../registry";
|
||||
import { pluginRegistry } from "./registry";
|
||||
import { FormItemProps } from "../d.ts";
|
||||
export type TaskInput = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export type TaskOutput = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export enum ContextScope {
|
||||
global,
|
||||
|
@ -28,17 +21,19 @@ export type TaskOutputDefine = {
|
|||
export type TaskInputDefine = FormItemProps;
|
||||
|
||||
export type PluginDefine = Registrable & {
|
||||
input: {
|
||||
default?: any;
|
||||
inputs?: {
|
||||
[key: string]: TaskInputDefine;
|
||||
};
|
||||
output: {
|
||||
outputs?: {
|
||||
[key: string]: TaskOutputDefine;
|
||||
};
|
||||
|
||||
autowire?: any;
|
||||
};
|
||||
|
||||
export interface TaskPlugin {
|
||||
getDefine(): PluginDefine;
|
||||
execute(input: TaskInput): Promise<TaskOutput>;
|
||||
export interface ITaskPlugin {
|
||||
execute(): Promise<void>;
|
||||
}
|
||||
|
||||
export type OutputVO = {
|
||||
|
@ -46,15 +41,3 @@ export type OutputVO = {
|
|||
title: string;
|
||||
value: any;
|
||||
};
|
||||
|
||||
export function IsTask(define: (() => PluginDefine) | PluginDefine) {
|
||||
return function (target: any) {
|
||||
if (define instanceof Function) {
|
||||
target.prototype.define = define();
|
||||
} else {
|
||||
target.prototype.define = define;
|
||||
}
|
||||
|
||||
pluginRegistry.install(target);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
// 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 { pluginRegistry } from "./registry";
|
||||
import { PluginDefine, TaskInputDefine, TaskOutputDefine } from "./api";
|
||||
|
||||
// 提供一个唯一 key
|
||||
export const PLUGIN_CLASS_KEY = "decorator:plugin";
|
||||
|
||||
export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
||||
console.log("is task plugin define:", define);
|
||||
return (target: any) => {
|
||||
console.log("is task plugin load:", target);
|
||||
// 将装饰的类,绑定到该装饰器,用于后续能获取到 class
|
||||
saveModule(PLUGIN_CLASS_KEY, target);
|
||||
// 保存一些元数据信息,任意你希望存的东西
|
||||
saveClassMetadata(
|
||||
PLUGIN_CLASS_KEY,
|
||||
{
|
||||
define,
|
||||
},
|
||||
target
|
||||
);
|
||||
// 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx
|
||||
Scope(ScopeEnum.Prototype)(target);
|
||||
|
||||
// 调用一下 Provide 装饰器,这样用户的 class 可以省略写 @Provide() 装饰器了
|
||||
Provide()(target);
|
||||
};
|
||||
}
|
||||
|
||||
export const PLUGIN_INPUT_KEY = "decorator:plugin:input";
|
||||
|
||||
export function TaskInput(input?: TaskInputDefine): PropertyDecorator {
|
||||
return (target, propertyKey) => {
|
||||
attachPropertyDataToClass(PLUGIN_INPUT_KEY, { input }, target, propertyKey, propertyKey as string);
|
||||
|
||||
attachClassMetadata(
|
||||
PLUGIN_CLASS_KEY,
|
||||
{
|
||||
inputs: {
|
||||
[propertyKey]: input,
|
||||
},
|
||||
},
|
||||
target
|
||||
);
|
||||
};
|
||||
//
|
||||
// return createCustomPropertyDecorator(CLASS_PROPS_KEY, {
|
||||
// input,
|
||||
// });
|
||||
}
|
||||
|
||||
// 装饰器内部的唯一 id
|
||||
export const PLUGIN_OUTPUT_KEY = "decorator:plugin:output";
|
||||
export function TaskOutput(output?: TaskOutputDefine): PropertyDecorator {
|
||||
return (target, propertyKey) => {
|
||||
attachPropertyDataToClass(PLUGIN_OUTPUT_KEY, { output }, target, propertyKey, propertyKey as string);
|
||||
|
||||
attachClassMetadata(
|
||||
PLUGIN_CLASS_KEY,
|
||||
{
|
||||
outputs: {
|
||||
[propertyKey]: output,
|
||||
},
|
||||
},
|
||||
target
|
||||
);
|
||||
};
|
||||
//
|
||||
// return createCustomPropertyDecorator(CLASS_PROPS_KEY, {
|
||||
// input,
|
||||
// });
|
||||
}
|
||||
|
||||
export type AutowireProp = {
|
||||
name?: string;
|
||||
};
|
||||
export const PLUGIN_AUTOWIRE_KEY = "decorator:plugin:autowire";
|
||||
|
||||
export function Autowire(props?: AutowireProp): PropertyDecorator {
|
||||
return (target, propertyKey) => {
|
||||
attachPropertyDataToClass(
|
||||
PLUGIN_AUTOWIRE_KEY,
|
||||
{
|
||||
autowire: {
|
||||
[propertyKey]: props,
|
||||
},
|
||||
},
|
||||
target,
|
||||
propertyKey,
|
||||
propertyKey as string
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function registerPlugins() {
|
||||
const modules = listModule(PLUGIN_CLASS_KEY);
|
||||
for (const mod of modules) {
|
||||
console.log("mod", mod);
|
||||
const define: PluginDefine = getClassMetadata(PLUGIN_CLASS_KEY, mod);
|
||||
console.log("define", define);
|
||||
const inputs = listPropertyDataFromClass(PLUGIN_INPUT_KEY, mod);
|
||||
console.log("inputs", inputs);
|
||||
for (const input of inputs) {
|
||||
define.inputs = {};
|
||||
_.merge(define.inputs, input.inputs);
|
||||
}
|
||||
|
||||
const outputs = listPropertyDataFromClass(PLUGIN_OUTPUT_KEY, mod);
|
||||
console.log("outputs", outputs);
|
||||
for (const output of outputs) {
|
||||
define.outputs = {};
|
||||
_.merge(define.outputs, output.outputs);
|
||||
}
|
||||
|
||||
const autowire = listPropertyDataFromClass(PLUGIN_AUTOWIRE_KEY, mod);
|
||||
console.log("autowire", autowire);
|
||||
for (const auto of autowire) {
|
||||
define.autowire = {};
|
||||
_.merge(define.autowire, auto.autowire);
|
||||
}
|
||||
|
||||
pluginRegistry.register(define.name, {
|
||||
define,
|
||||
target: mod,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
export * from "./api";
|
||||
export * from "./registry";
|
||||
export * from "./abstract-plugin";
|
||||
export * from "./decorator";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Registry } from "../registry";
|
||||
import { AbstractPlugin } from "./abstract-plugin";
|
||||
|
||||
// @ts-ignore
|
||||
export const pluginRegistry = new Registry<typeof AbstractPlugin>();
|
||||
export const pluginRegistry = new Registry();
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import { ILogger } from "@midwayjs/logger";
|
||||
import { ITaskPlugin } from "../api";
|
||||
import { Autowire, IsTaskPlugin, TaskInput } from "../decorator";
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: "EchoPlugin",
|
||||
title: "测试插件",
|
||||
desc: "test",
|
||||
})
|
||||
export class EchoPlugin implements ITaskPlugin {
|
||||
@TaskInput({
|
||||
title: "测试属性",
|
||||
component: {
|
||||
name: "text",
|
||||
},
|
||||
})
|
||||
test?: string;
|
||||
|
||||
@Autowire()
|
||||
// @ts-ignore
|
||||
logger: ILogger;
|
||||
|
||||
async execute(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
|
@ -4,36 +4,16 @@ export type Registrable = {
|
|||
desc?: string;
|
||||
};
|
||||
|
||||
export abstract class AbstractRegistrable<T extends Registrable> {
|
||||
// @ts-ignore
|
||||
define: T;
|
||||
|
||||
getDefine(): T {
|
||||
return this.define;
|
||||
}
|
||||
}
|
||||
export class Registry<T extends typeof AbstractRegistrable> {
|
||||
export type RegistryItem = {
|
||||
define: Registrable;
|
||||
target: any;
|
||||
};
|
||||
export class Registry {
|
||||
storage: {
|
||||
[key: string]: T;
|
||||
[key: string]: RegistryItem;
|
||||
} = {};
|
||||
|
||||
install(pluginClass: T) {
|
||||
if (pluginClass == null) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
const plugin = new pluginClass();
|
||||
delete plugin.define;
|
||||
const define = plugin.getDefine();
|
||||
let defineName = define.name;
|
||||
if (defineName == null) {
|
||||
defineName = plugin.name;
|
||||
}
|
||||
|
||||
this.register(defineName, pluginClass);
|
||||
}
|
||||
|
||||
register(key: string, value: T) {
|
||||
register(key: string, value: RegistryItem) {
|
||||
if (!key || value == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -68,12 +48,10 @@ export class Registry<T extends typeof AbstractRegistrable> {
|
|||
}
|
||||
|
||||
getDefine(key: string) {
|
||||
const PluginClass = this.storage[key];
|
||||
if (!PluginClass) {
|
||||
const item = this.storage[key];
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
const plugin = new PluginClass();
|
||||
return plugin.define;
|
||||
return item.define;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin, utils } from "@certd/pipeline";
|
||||
import Core from "@alicloud/pop-core";
|
||||
// @ts-ignore
|
||||
import { ROAClient } from "@alicloud/pop-core";
|
||||
import { AliyunAccess } from "../../access";
|
||||
import { K8sClient } from "@certd/plugin-util";
|
||||
import { appendTimeSuffix } from "../../utils";
|
||||
|
||||
const ROAClient = Core.ROAClient;
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "DeployCertToAliyunAckIngress",
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin } from "@certd/pipeline";
|
||||
import dayjs from "dayjs";
|
||||
import Core from "@alicloud/pop-core";
|
||||
import RPCClient from "@alicloud/pop-core";
|
||||
import { AliyunAccess } from "../../access";
|
||||
import { appendTimeSuffix, checkRet, ZoneOptions } from "../../utils";
|
||||
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
import { AbstractAccess, IsAccess } from "@certd/pipeline";
|
||||
import { IsAccess, IsAccessInput } from "@certd/pipeline";
|
||||
|
||||
@IsAccess({
|
||||
name: "dnspod",
|
||||
title: "dnspod",
|
||||
desc: "腾讯云的域名解析接口已迁移到dnspod",
|
||||
input: {
|
||||
id: {
|
||||
title: "账户id",
|
||||
component: {
|
||||
placeholder: "dnspod接口账户id",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
},
|
||||
token: {
|
||||
title: "token",
|
||||
component: {
|
||||
placeholder: "开放接口token",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
},
|
||||
},
|
||||
})
|
||||
export class DnspodAccess extends AbstractAccess {
|
||||
export class DnspodAccess {
|
||||
@IsAccessInput({
|
||||
title: "token",
|
||||
component: {
|
||||
placeholder: "开放接口token",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
})
|
||||
token = "";
|
||||
@IsAccessInput({
|
||||
title: "账户id",
|
||||
component: {
|
||||
placeholder: "dnspod接口账户id",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
})
|
||||
id = "";
|
||||
}
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
import { AbstractAccess, IsAccess } from "@certd/pipeline";
|
||||
import { IsAccess, IsAccessInput } from "@certd/pipeline";
|
||||
|
||||
@IsAccess({
|
||||
name: "tencent",
|
||||
title: "腾讯云",
|
||||
input: {
|
||||
secretId: {
|
||||
title: "secretId",
|
||||
component: {
|
||||
placeholder: "secretId",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
},
|
||||
secretKey: {
|
||||
title: "secretKey",
|
||||
component: {
|
||||
placeholder: "secretKey",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
},
|
||||
},
|
||||
})
|
||||
export class TencentAccess extends AbstractAccess {
|
||||
export class TencentAccess {
|
||||
@IsAccessInput({
|
||||
title: "secretId",
|
||||
component: {
|
||||
placeholder: "secretId",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
})
|
||||
secretId = "";
|
||||
@IsAccessInput({
|
||||
title: "secretKey",
|
||||
component: {
|
||||
placeholder: "secretKey",
|
||||
},
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
})
|
||||
secretKey = "";
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { AbstractDnsProvider, CreateRecordOptions, IDnsProvider, IsDnsProvider, RemoveRecordOptions } from "@certd/pipeline";
|
||||
import { CreateRecordOptions, HttpClient, IDnsProvider, IsDnsProvider, RemoveRecordOptions } from "@certd/pipeline";
|
||||
import _ from "lodash";
|
||||
import { DnspodAccess } from "../access";
|
||||
import { Inject } from "@midwayjs/decorator";
|
||||
import { ILogger } from "@midwayjs/core";
|
||||
|
||||
@IsDnsProvider({
|
||||
name: "dnspod",
|
||||
|
@ -8,11 +10,17 @@ import { DnspodAccess } from "../access";
|
|||
desc: "腾讯云的域名解析接口已迁移到dnspod",
|
||||
accessType: "dnspod",
|
||||
})
|
||||
export class DnspodDnsProvider extends AbstractDnsProvider implements IDnsProvider {
|
||||
export class DnspodDnsProvider implements IDnsProvider {
|
||||
@Inject()
|
||||
http!: HttpClient;
|
||||
|
||||
@Inject()
|
||||
access!: DnspodAccess;
|
||||
@Inject()
|
||||
logger!: ILogger;
|
||||
|
||||
loginToken: any;
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async onInit() {
|
||||
const access: DnspodAccess = this.access as DnspodAccess;
|
||||
this.loginToken = access.id + "," + access.token;
|
||||
|
|
|
@ -1,56 +1,64 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin } from "@certd/pipeline";
|
||||
import { IAccessService, IsTaskPlugin, RunStrategy, TaskInput, ITaskPlugin } from "@certd/pipeline";
|
||||
import tencentcloud from "tencentcloud-sdk-nodejs/index";
|
||||
import { TencentAccess } from "../../access";
|
||||
import { Inject } from "@midwayjs/decorator";
|
||||
import { ILogger } from "@midwayjs/core";
|
||||
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "DeployCertToTencentCDN",
|
||||
title: "部署到腾讯云CDN",
|
||||
input: {
|
||||
domainName: {
|
||||
title: "cdn加速域名",
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
},
|
||||
certName: {
|
||||
title: "证书名称",
|
||||
helper: "证书上传后将以此参数作为名称前缀",
|
||||
},
|
||||
cert: {
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
from: "CertApply",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
accessId: {
|
||||
title: "Access提供者",
|
||||
helper: "access 授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@IsTaskPlugin({
|
||||
name: "DeployCertToTencentCDN",
|
||||
title: "部署到腾讯云CDN",
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
},
|
||||
output: {},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class DeployToCdnPlugin extends AbstractPlugin implements TaskPlugin {
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
const { cert, accessId } = input;
|
||||
const accessProvider: TencentAccess = (await this.accessService.getById(accessId)) as TencentAccess;
|
||||
const client = this.getClient(accessProvider);
|
||||
const params = this.buildParams(input, cert);
|
||||
await this.doRequest(client, params);
|
||||
export class DeployToCdnPlugin implements ITaskPlugin {
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
from: "CertApply",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: any;
|
||||
|
||||
return {};
|
||||
@TaskInput({
|
||||
title: "Access提供者",
|
||||
helper: "access 授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "证书名称",
|
||||
helper: "证书上传后将以此参数作为名称前缀",
|
||||
})
|
||||
certName!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "cdn加速域名",
|
||||
rules: [{ required: true, message: "该项必填" }],
|
||||
})
|
||||
domainName!: string;
|
||||
|
||||
@Inject()
|
||||
accessService!: IAccessService;
|
||||
|
||||
@Inject()
|
||||
logger!: ILogger;
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const accessProvider: TencentAccess = (await this.accessService.getById(this.accessId)) as TencentAccess;
|
||||
const client = this.getClient(accessProvider);
|
||||
const params = this.buildParams();
|
||||
await this.doRequest(client, params);
|
||||
}
|
||||
|
||||
getClient(accessProvider: TencentAccess) {
|
||||
|
@ -72,17 +80,16 @@ export class DeployToCdnPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
return new CdnClient(clientConfig);
|
||||
}
|
||||
|
||||
buildParams(props: TaskInput, cert: any) {
|
||||
const { domainName } = props;
|
||||
buildParams() {
|
||||
return {
|
||||
Https: {
|
||||
Switch: "on",
|
||||
CertInfo: {
|
||||
Certificate: cert.crt,
|
||||
PrivateKey: cert.key,
|
||||
Certificate: this.cert.crt,
|
||||
PrivateKey: this.cert.key,
|
||||
},
|
||||
},
|
||||
Domain: domainName,
|
||||
Domain: this.domainName,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,99 +1,115 @@
|
|||
import { AbstractPlugin, IsTask, RunStrategy, TaskInput, TaskOutput, TaskPlugin, utils } from "@certd/pipeline";
|
||||
import { IAccessService, IsTaskPlugin, ITaskPlugin, 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";
|
||||
|
||||
@IsTask(() => {
|
||||
return {
|
||||
name: "DeployCertToTencentCLB",
|
||||
title: "部署到腾讯云CLB",
|
||||
desc: "暂时只支持单向认证证书,暂时只支持通用负载均衡",
|
||||
input: {
|
||||
region: {
|
||||
title: "大区",
|
||||
value: "ap-guangzhou",
|
||||
component: {
|
||||
name: "a-select",
|
||||
options: [{ value: "ap-guangzhou" }],
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
domain: {
|
||||
title: "域名",
|
||||
required: true,
|
||||
helper: "要更新的支持https的负载均衡的域名",
|
||||
},
|
||||
loadBalancerId: {
|
||||
title: "负载均衡ID",
|
||||
helper: "如果没有配置,则根据域名匹配负载均衡下的监听器(根据域名匹配时暂时只支持前100个)",
|
||||
required: true,
|
||||
},
|
||||
listenerId: {
|
||||
title: "监听器ID",
|
||||
helper: "如果没有配置,则根据域名或负载均衡id匹配监听器",
|
||||
},
|
||||
certName: {
|
||||
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: "DeployCertToTencentCLB",
|
||||
title: "部署到腾讯云CLB",
|
||||
desc: "暂时只支持单向认证证书,暂时只支持通用负载均衡",
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
default: {
|
||||
strategy: {
|
||||
runStrategy: RunStrategy.SkipWhenSucceed,
|
||||
},
|
||||
},
|
||||
output: {},
|
||||
};
|
||||
},
|
||||
})
|
||||
export class DeployToClbPlugin extends AbstractPlugin implements TaskPlugin {
|
||||
async execute(input: TaskInput): Promise<TaskOutput> {
|
||||
const { accessId, region, domain } = input;
|
||||
const accessProvider = (await this.accessService.getById(accessId)) as TencentAccess;
|
||||
const client = this.getClient(accessProvider, region);
|
||||
export class DeployToClbPlugin implements ITaskPlugin {
|
||||
@TaskInput({
|
||||
title: "大区",
|
||||
value: "ap-guangzhou",
|
||||
component: {
|
||||
name: "a-select",
|
||||
options: [{ value: "ap-guangzhou" }],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
region!: string;
|
||||
|
||||
const lastCertId = await this.getCertIdFromProps(client, input);
|
||||
if (!domain) {
|
||||
await this.updateListener(client, input);
|
||||
@TaskInput({
|
||||
title: "证书名称前缀",
|
||||
})
|
||||
certName!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "负载均衡ID",
|
||||
helper: "如果没有配置,则根据域名匹配负载均衡下的监听器(根据域名匹配时暂时只支持前100个)",
|
||||
required: true,
|
||||
})
|
||||
loadBalancerId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "监听器ID",
|
||||
helper: "如果没有配置,则根据域名或负载均衡id匹配监听器",
|
||||
})
|
||||
listenerId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "域名",
|
||||
required: true,
|
||||
helper: "要更新的支持https的负载均衡的域名",
|
||||
})
|
||||
domain!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: any;
|
||||
|
||||
@TaskInput({
|
||||
title: "Access提供者",
|
||||
helper: "access授权",
|
||||
component: {
|
||||
name: "pi-access-selector",
|
||||
type: "tencent",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@Inject()
|
||||
accessService!: IAccessService;
|
||||
|
||||
@Inject()
|
||||
logger!: ILogger;
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const accessProvider = (await this.accessService.getById(this.accessId)) as TencentAccess;
|
||||
const client = this.getClient(accessProvider, this.region);
|
||||
|
||||
const lastCertId = await this.getCertIdFromProps(client);
|
||||
if (!this.domain) {
|
||||
await this.updateListener(client);
|
||||
} else {
|
||||
await this.updateByDomainAttr(client, input);
|
||||
await this.updateByDomainAttr(client);
|
||||
}
|
||||
|
||||
try {
|
||||
await utils.sleep(2000);
|
||||
let newCertId = await this.getCertIdFromProps(client, input);
|
||||
let newCertId = await this.getCertIdFromProps(client);
|
||||
if ((lastCertId && newCertId === lastCertId) || (!lastCertId && !newCertId)) {
|
||||
await utils.sleep(2000);
|
||||
newCertId = await this.getCertIdFromProps(client, input);
|
||||
newCertId = await this.getCertIdFromProps(client);
|
||||
}
|
||||
if (newCertId === lastCertId) {
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
this.logger.info("腾讯云证书ID:", newCertId);
|
||||
} catch (e) {
|
||||
this.logger.warn("查询腾讯云证书失败", e);
|
||||
}
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
async getCertIdFromProps(client: any, input: TaskInput) {
|
||||
const listenerRet = await this.getListenerList(client, input.loadBalancerId, [input.listenerId]);
|
||||
return this.getCertIdFromListener(listenerRet[0], input.domain);
|
||||
async getCertIdFromProps(client: any) {
|
||||
const listenerRet = await this.getListenerList(client, this.loadBalancerId, [this.listenerId]);
|
||||
return this.getCertIdFromListener(listenerRet[0], this.domain);
|
||||
}
|
||||
|
||||
getCertIdFromListener(listener: any, domain: string) {
|
||||
|
@ -115,28 +131,28 @@ export class DeployToClbPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
return certId;
|
||||
}
|
||||
|
||||
async updateListener(client: any, props: TaskInput) {
|
||||
const params = this.buildProps(props);
|
||||
async updateListener(client: any) {
|
||||
const params = this.buildProps();
|
||||
const ret = await client.ModifyListener(params);
|
||||
this.checkRet(ret);
|
||||
this.logger.info("设置腾讯云CLB证书成功:", ret.RequestId, "->loadBalancerId:", props.loadBalancerId, "listenerId", props.listenerId);
|
||||
this.logger.info("设置腾讯云CLB证书成功:", ret.RequestId, "->loadBalancerId:", this.loadBalancerId, "listenerId", this.listenerId);
|
||||
return ret;
|
||||
}
|
||||
|
||||
async updateByDomainAttr(client: any, props: TaskInput) {
|
||||
const params: any = this.buildProps(props);
|
||||
params.Domain = props.domain;
|
||||
async updateByDomainAttr(client: any) {
|
||||
const params: any = this.buildProps();
|
||||
params.Domain = this.domain;
|
||||
const ret = await client.ModifyDomainAttributes(params);
|
||||
this.checkRet(ret);
|
||||
this.logger.info(
|
||||
"设置腾讯云CLB证书(sni)成功:",
|
||||
ret.RequestId,
|
||||
"->loadBalancerId:",
|
||||
props.loadBalancerId,
|
||||
this.loadBalancerId,
|
||||
"listenerId",
|
||||
props.listenerId,
|
||||
this.listenerId,
|
||||
"domain:",
|
||||
props.domain
|
||||
this.domain
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
@ -146,26 +162,25 @@ export class DeployToClbPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
}
|
||||
return name + "-" + dayjs().format("YYYYMMDD-HHmmss");
|
||||
}
|
||||
buildProps(props: TaskInput) {
|
||||
const { certName, cert } = props;
|
||||
buildProps() {
|
||||
return {
|
||||
Certificate: {
|
||||
SSLMode: "UNIDIRECTIONAL", // 单向认证
|
||||
CertName: this.appendTimeSuffix(certName || cert.domain),
|
||||
CertKey: cert.key,
|
||||
CertContent: cert.crt,
|
||||
CertName: this.appendTimeSuffix(this.certName || this.cert.domain),
|
||||
CertKey: this.cert.key,
|
||||
CertContent: this.cert.crt,
|
||||
},
|
||||
LoadBalancerId: props.loadBalancerId,
|
||||
ListenerId: props.listenerId,
|
||||
LoadBalancerId: this.loadBalancerId,
|
||||
ListenerId: this.listenerId,
|
||||
};
|
||||
}
|
||||
|
||||
async getCLBList(client: any, props: TaskInput) {
|
||||
async getCLBList(client: any) {
|
||||
const params = {
|
||||
Limit: 100, // 最大暂时只支持100个,暂时没做翻页
|
||||
OrderBy: "CreateTime",
|
||||
OrderType: 0,
|
||||
...props.DescribeLoadBalancers,
|
||||
// ...this.DescribeLoadBalancers,
|
||||
};
|
||||
const ret = await client.DescribeLoadBalancers(params);
|
||||
this.checkRet(ret);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a59e66a11d667dc99b425b14cd6fde7468a8725b
|
||||
Subproject commit 70f3fd5359ac27b6dbd452f30fbf6630d4c9fa26
|
Loading…
Reference in New Issue