From d3619ad60f8ef32744e25a4428728f359f4efb9a Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 21 Jan 2021 23:59:06 +0800 Subject: [PATCH] refactor: ui prepare --- .gitignore | 1 + lerna.json | 3 +- other/certd-ui/src/api/api.plugins.js | 9 ++ other/certd-ui/vue.config.js | 9 ++ .../api/src/dns-provider/abstract-provider.js | 34 +++++++ packages/api/src/dns-provider/index.js | 36 +------- .../api/src/dns-provider/provider-registry.js | 26 ++++++ packages/api/src/index.js | 4 +- packages/api/src/plugin/abstract-plugin.js | 75 ++++++++++++++++ packages/api/src/plugin/index.js | 74 +-------------- packages/api/src/plugin/plugin-registry.js | 27 ++++++ packages/certd/src/index.js | 19 +--- packages/executor/src/index.js | 48 ++-------- .../plugins/src/aliyun/deploy-to-cdn/index.js | 89 +++++++++---------- .../src/aliyun/upload-to-aliyun/index.js | 61 ++++++------- packages/plugins/src/index.js | 11 ++- packages/providers/src/index.js | 11 ++- 17 files changed, 292 insertions(+), 245 deletions(-) create mode 100644 other/certd-ui/src/api/api.plugins.js create mode 100644 other/certd-ui/vue.config.js create mode 100644 packages/api/src/dns-provider/abstract-provider.js create mode 100644 packages/api/src/dns-provider/provider-registry.js create mode 100644 packages/api/src/plugin/abstract-plugin.js create mode 100644 packages/api/src/plugin/plugin-registry.js diff --git a/.gitignore b/.gitignore index da6db3b0..1063e719 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ out gen node_modules/ /test/*.private.* +/other /other/node-acme-client/.idea/ /*.log /other/certd-run diff --git a/lerna.json b/lerna.json index 7bb41293..a366bb75 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,7 @@ { "packages": [ - "packages/*" + "packages/*", + "other/*" ], "version": "0.1.11" } diff --git a/other/certd-ui/src/api/api.plugins.js b/other/certd-ui/src/api/api.plugins.js new file mode 100644 index 00000000..a1e7f98b --- /dev/null +++ b/other/certd-ui/src/api/api.plugins.js @@ -0,0 +1,9 @@ +import { request } from './service' + +export default { + list () { + return request({ + url: '/plugins/list' + }) + } +} diff --git a/other/certd-ui/vue.config.js b/other/certd-ui/vue.config.js new file mode 100644 index 00000000..7893d571 --- /dev/null +++ b/other/certd-ui/vue.config.js @@ -0,0 +1,9 @@ +export default { + devServer: { + proxy: { + '/': { + target: 'http://localhost:3000/' + } + } + } +} diff --git a/packages/api/src/dns-provider/abstract-provider.js b/packages/api/src/dns-provider/abstract-provider.js new file mode 100644 index 00000000..5c59e982 --- /dev/null +++ b/packages/api/src/dns-provider/abstract-provider.js @@ -0,0 +1,34 @@ +import _ from 'lodash-es' +import logger from '../utils/util.log.js' +export class AbstractDnsProvider { + constructor () { + this.logger = logger + } + + async createRecord ({ fullRecord, type, value }) { + throw new Error('请实现 createRecord 方法') + } + + async removeRecord ({ fullRecord, type, value, record }) { + throw new Error('请实现 removeRecord 方法') + } + + async getDomainList () { + throw new Error('请实现 getDomainList 方法') + } + + async matchDomain (dnsRecord, domainPropName) { + const list = await this.getDomainList() + let domain = null + for (const item of list) { + if (_.endsWith(dnsRecord, item[domainPropName])) { + domain = item + break + } + } + if (!domain) { + throw new Error('找不到域名,请检查域名是否正确:' + dnsRecord) + } + return domain + } +} diff --git a/packages/api/src/dns-provider/index.js b/packages/api/src/dns-provider/index.js index 5c59e982..c51f5b60 100644 --- a/packages/api/src/dns-provider/index.js +++ b/packages/api/src/dns-provider/index.js @@ -1,34 +1,2 @@ -import _ from 'lodash-es' -import logger from '../utils/util.log.js' -export class AbstractDnsProvider { - constructor () { - this.logger = logger - } - - async createRecord ({ fullRecord, type, value }) { - throw new Error('请实现 createRecord 方法') - } - - async removeRecord ({ fullRecord, type, value, record }) { - throw new Error('请实现 removeRecord 方法') - } - - async getDomainList () { - throw new Error('请实现 getDomainList 方法') - } - - async matchDomain (dnsRecord, domainPropName) { - const list = await this.getDomainList() - let domain = null - for (const item of list) { - if (_.endsWith(dnsRecord, item[domainPropName])) { - domain = item - break - } - } - if (!domain) { - throw new Error('找不到域名,请检查域名是否正确:' + dnsRecord) - } - return domain - } -} +export { providerRegistry } from './provider-registry.js' +export { AbstractDnsProvider } from './abstract-provider.js' diff --git a/packages/api/src/dns-provider/provider-registry.js b/packages/api/src/dns-provider/provider-registry.js new file mode 100644 index 00000000..b4e9a7bc --- /dev/null +++ b/packages/api/src/dns-provider/provider-registry.js @@ -0,0 +1,26 @@ + +export class ProviderRegistry { + constructor () { + this.providers = {} + } + + install (provider) { + if (provider == null) { + return + } + if (this.providers == null) { + this.providers = {} + } + const name = provider.name || (provider.define && provider.define.name) + this.providers[name] = provider + } + + get (name) { + if (name) { + return this.providers[name] + } + throw new Error(`找不到授权提供者:${name}`) + } +} + +export const providerRegistry = new ProviderRegistry() diff --git a/packages/api/src/index.js b/packages/api/src/index.js index 9eed1f95..2f1374d5 100644 --- a/packages/api/src/index.js +++ b/packages/api/src/index.js @@ -1,4 +1,4 @@ -export { AbstractDnsProvider } from './dns-provider/index.js' +export * from './dns-provider/index.js' +export * from './plugin/index.js' export { Store } from './store/store.js' export { util } from './utils/index.js' -export { AbstractPlugin } from './plugin/index.js' diff --git a/packages/api/src/plugin/abstract-plugin.js b/packages/api/src/plugin/abstract-plugin.js new file mode 100644 index 00000000..ff0857d7 --- /dev/null +++ b/packages/api/src/plugin/abstract-plugin.js @@ -0,0 +1,75 @@ +import fs from 'fs' +import logger from '../utils/util.log.js' +import dayjs from 'dayjs' +import Sleep from '../utils/util.sleep.js' + +import { pluginRegistry } from './plugin-registry.js' + +export class AbstractPlugin { + constructor ({ accessProviders }) { + this.logger = logger + this.accessProviders = accessProviders + } + + appendTimeSuffix (name) { + if (name == null) { + name = 'certd' + } + return name + '-' + dayjs().format('YYYYMMDD-HHmmss') + } + + async executeFromContextFile (options = {}) { + const { contextPath } = options + const contextJson = fs.readFileSync(contextPath) + const context = JSON.parse(contextJson) + options.context = context + await this.doExecute(options) + fs.writeFileSync(JSON.stringify(context)) + } + + async doExecute (options) { + try { + return await this.execute(options) + } catch (e) { + logger.error('插件执行出错:', e) + throw e + } + } + + /** + * 执行 + * @param options + * @returns {Promise} + */ + async execute (options) { + console.error('请实现此方法,context:', options.context) + } + + async doRollback (options) { + try { + return await this.rollback(options) + } catch (e) { + logger.error('插件rollback出错:', e) + throw e + } + } + + /** + * 回退,如有必要 + * @param options + */ + async rollback (options) { + console.error('请实现此方法,rollback:', options.context) + } + + getAccessProvider (accessProvider, accessProviders = this.accessProviders) { + if (typeof accessProvider === 'string' && accessProviders) { + accessProvider = accessProviders[accessProvider] + } + return accessProvider + } + + async sleep (time) { + await Sleep(time) + } +} diff --git a/packages/api/src/plugin/index.js b/packages/api/src/plugin/index.js index 45a0e68f..c70bf60e 100644 --- a/packages/api/src/plugin/index.js +++ b/packages/api/src/plugin/index.js @@ -1,72 +1,2 @@ -import fs from 'fs' -import logger from '../utils/util.log.js' -import dayjs from 'dayjs' -import Sleep from '../utils/util.sleep.js' -export class AbstractPlugin { - constructor ({ accessProviders }) { - this.logger = logger - this.accessProviders = accessProviders - } - - appendTimeSuffix (name) { - if (name == null) { - name = 'certd' - } - return name + '-' + dayjs().format('YYYYMMDD-HHmmss') - } - - async executeFromContextFile (options = {}) { - const { contextPath } = options - const contextJson = fs.readFileSync(contextPath) - const context = JSON.parse(contextJson) - options.context = context - await this.doExecute(options) - fs.writeFileSync(JSON.stringify(context)) - } - - async doExecute (options) { - try { - return await this.execute(options) - } catch (e) { - logger.error('插件执行出错:', e) - throw e - } - } - - /** - * 执行 - * @param options - * @returns {Promise} - */ - async execute (options) { - console.error('请实现此方法,context:', options.context) - } - - async doRollback (options) { - try { - return await this.rollback(options) - } catch (e) { - logger.error('插件rollback出错:', e) - throw e - } - } - - /** - * 回退,如有必要 - * @param options - */ - async rollback (options) { - console.error('请实现此方法,rollback:', options.context) - } - - getAccessProvider (accessProvider, accessProviders = this.accessProviders) { - if (typeof accessProvider === 'string' && accessProviders) { - accessProvider = accessProviders[accessProvider] - } - return accessProvider - } - - async sleep (time) { - await Sleep(time) - } -} +export { pluginRegistry } from './plugin-registry.js' +export { AbstractPlugin } from './abstract-plugin.js' diff --git a/packages/api/src/plugin/plugin-registry.js b/packages/api/src/plugin/plugin-registry.js new file mode 100644 index 00000000..d18d9c36 --- /dev/null +++ b/packages/api/src/plugin/plugin-registry.js @@ -0,0 +1,27 @@ + +export class PluginRegistry { + constructor () { + this.plugins = {} + } + + install (plugin) { + if (plugin == null) { + return + } + if (this.plugins == null) { + this.plugins = {} + } + const name = plugin.name || (plugin.define && plugin.define.name) + this.plugins[name] = plugin + } + + get (name) { + if (name) { + return this.plugins[name] + } + + throw new Error(`找不到${name}插件`) + } +} + +export const pluginRegistry = new PluginRegistry() diff --git a/packages/certd/src/index.js b/packages/certd/src/index.js index 6cdfd192..86b4f2e4 100644 --- a/packages/certd/src/index.js +++ b/packages/certd/src/index.js @@ -1,27 +1,12 @@ -import { util, Store } from '@certd/api' +import { util, Store, pluginRegistry } from '@certd/api' import { AcmeService } from './acme.js' import { FileStore } from './store/file-store.js' import { CertStore } from './store/cert-store.js' import dayjs from 'dayjs' import forge from 'node-forge' -import DefaultProviders from '@certd/providers' -import _ from 'lodash-es' const logger = util.logger -const AccessProviderClasses = {} -function install (providerClass) { - AccessProviderClasses[providerClass.name()] = providerClass -} -logger.info('use') -_.forEach(DefaultProviders, item => { - logger.info('use:', item.name()) - install(item) -}) export class Certd { - static use (providerClass) { - install(providerClass) - } - constructor (options) { this.options = options this.email = options.cert.email @@ -139,7 +124,7 @@ export class Certd { createProviderByType (type, options) { try { - const Provider = AccessProviderClasses[type] + const Provider = pluginRegistry.get(type) return new Provider(options) } catch (e) { throw new Error('暂不支持此dnsProvider,请先use该provider:' + type, e) diff --git a/packages/executor/src/index.js b/packages/executor/src/index.js index b667b326..ecd1b63c 100644 --- a/packages/executor/src/index.js +++ b/packages/executor/src/index.js @@ -1,11 +1,16 @@ import { Certd } from '@certd/certd' -import DefaultPlugins from '@certd/plugins' -import { util } from '@certd/api' +import { pluginRegistry, util } from '@certd/api' import _ from 'lodash-es' import dayjs from 'dayjs' import { Trace } from './trace.js' +import DefaultPlugins from '@certd/plugins' +import DefaultProviders from '@certd/providers' const logger = util.logger +// 安装默认插件和授权提供者 +DefaultPlugins.install() +DefaultProviders.install() + function createDefaultOptions () { return { args: { @@ -18,44 +23,9 @@ function createDefaultOptions () { } export class Executor { constructor () { - this.usePlugins(DefaultPlugins) this.trace = new Trace() } - useProviders (providers) { - if (providers) { - _.forEach(item => { - Certd.use(item) - }) - } - } - - useProvider (provider) { - Certd.use(provider) - } - - usePlugin (plugin) { - if (plugin == null) { - return - } - if (this.plugins == null) { - this.plugins = {} - } - this.plugins[plugin.name] = plugin - if (plugin.define) { - const define = plugin.define() - this.plugins[define.name] = plugin - } - } - - usePlugins (plugins) { - if (plugins) { - _.forEach(plugins, item => { - this.usePlugin(item) - }) - } - } - async run (options) { logger.info('------------------- Cert-D ---------------------') try { @@ -70,7 +40,7 @@ export class Executor { async doRun (options) { // 申请证书 logger.info('任务开始') - const certd = new Certd(options, this.providers) + const certd = new Certd(options) const cert = await this.runCertd(certd) if (cert == null) { throw new Error('申请证书失败') @@ -165,7 +135,7 @@ export class Executor { async runTask ({ options, task, cert, context, deploy, trace }) { const taskType = task.type - const Plugin = this.plugins[taskType] + const Plugin = pluginRegistry.get(taskType) const deployName = deploy.deployName const taskName = task.taskName if (Plugin == null) { diff --git a/packages/plugins/src/aliyun/deploy-to-cdn/index.js b/packages/plugins/src/aliyun/deploy-to-cdn/index.js index d14a80fb..bd9de486 100644 --- a/packages/plugins/src/aliyun/deploy-to-cdn/index.js +++ b/packages/plugins/src/aliyun/deploy-to-cdn/index.js @@ -1,54 +1,51 @@ import { AbstractAliyunPlugin } from '../../aliyun/abstract-aliyun.js' import Core from '@alicloud/pop-core' import dayjs from 'dayjs' -export class DeployCertToAliyunCDN extends AbstractAliyunPlugin { - /** - * 插件定义 - * 名称 - * 入参 - * 出参 - */ - static define () { - return { - name: 'deployCertToAliyunCDN', - label: '部署到阿里云CDN', - input: { - domainName: { - label: 'cdn加速域名', - required: true - }, - certName: { - label: '证书名称' - }, - from: { - value: 'upload', - label: '证书来源', - options: [ - { value: 'upload', label: '直接上传' }, - { value: 'cas', label: '从证书库', desc: '需要uploadCertToAliyun作为前置任务' } - ], - required: true - }, - // serverCertificateStatus: { - // label: '启用https', - // options: [ - // { value: 'on', label: '开启HTTPS,并更新证书' }, - // { value: 'auto', label: '若HTTPS开启则更新,未开启不更新' } - // ], - // required:true - // }, - accessProvider: { - label: 'Access提供者', - type: [String, Object], - desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象', - options: 'accessProviders[type=aliyun]', - required: true - } - }, - output: { - } +const define = { + name: 'deployCertToAliyunCDN', + label: '部署到阿里云CDN', + input: { + domainName: { + label: 'cdn加速域名', + required: true + }, + certName: { + label: '证书名称' + }, + from: { + value: 'upload', + label: '证书来源', + options: [ + { value: 'upload', label: '直接上传' }, + { value: 'cas', label: '从证书库', desc: '需要uploadCertToAliyun作为前置任务' } + ], + required: true + }, + // serverCertificateStatus: { + // label: '启用https', + // options: [ + // { value: 'on', label: '开启HTTPS,并更新证书' }, + // { value: 'auto', label: '若HTTPS开启则更新,未开启不更新' } + // ], + // required:true + // }, + accessProvider: { + label: 'Access提供者', + type: [String, Object], + desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象', + options: 'accessProviders[type=aliyun]', + required: true } + }, + output: { + + } +} + +export class DeployCertToAliyunCDN extends AbstractAliyunPlugin { + static define () { + return define } async execute ({ cert, props, context }) { diff --git a/packages/plugins/src/aliyun/upload-to-aliyun/index.js b/packages/plugins/src/aliyun/upload-to-aliyun/index.js index 557170cc..0b4b22fa 100644 --- a/packages/plugins/src/aliyun/upload-to-aliyun/index.js +++ b/packages/plugins/src/aliyun/upload-to-aliyun/index.js @@ -1,38 +1,35 @@ import Core from '@alicloud/pop-core' import { AbstractAliyunPlugin } from '../abstract-aliyun.js' -export class UploadCertToAliyun extends AbstractAliyunPlugin { - /** - * 插件定义 - * 名称 - * 入参 - * 出参 - */ - static define () { - return { - name: 'uploadCertToAliyun', - label: '上传证书到阿里云', - input: { - name: { - label: '证书名称' - }, - regionId: { - label: '大区', - value: 'cn-hangzhou' - }, - accessProvider: { - label: 'Access提供者', - type: [String, Object], - desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象', - options: 'accessProviders[type=aliyun]' - } - }, - output: { - aliyunCertId: { - type: String, - desc: '上传成功后的阿里云CertId' - } - } + +const define = { + name: 'uploadCertToAliyun', + label: '上传证书到阿里云', + input: { + name: { + label: '证书名称' + }, + regionId: { + label: '大区', + value: 'cn-hangzhou' + }, + accessProvider: { + label: 'Access提供者', + type: [String, Object], + desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象', + options: 'accessProviders[type=aliyun]' } + }, + output: { + aliyunCertId: { + type: String, + desc: '上传成功后的阿里云CertId' + } + } +} + +export class UploadCertToAliyun extends AbstractAliyunPlugin { + static define () { + return define } getClient (aliyunProvider) { diff --git a/packages/plugins/src/index.js b/packages/plugins/src/index.js index 289c78c8..e41db769 100644 --- a/packages/plugins/src/index.js +++ b/packages/plugins/src/index.js @@ -1,3 +1,4 @@ +import _ from 'lodash-es' import { UploadCertToAliyun } from './aliyun/upload-to-aliyun/index.js' import { DeployCertToAliyunCDN } from './aliyun/deploy-to-cdn/index.js' @@ -8,8 +9,9 @@ import { DeployCertToTencentCDN } from './tencent/deploy-to-cdn/index.js' import { DeployCertToTencentCLB } from './tencent/deploy-to-clb/index.js' import { DeployCertToTencentTKEIngress } from './tencent/deploy-to-tke-ingress/index.js' +import { pluginRegistry } from '@certd/api' -export default { +export const DefaultPlugins = { UploadCertToAliyun, DeployCertToAliyunCDN, UploadCertToTencent, @@ -17,3 +19,10 @@ export default { DeployCertToTencentCDN, DeployCertToTencentCLB } +export default { + install () { + _.forEach(DefaultPlugins, item => { + pluginRegistry.install(item) + }) + } +} diff --git a/packages/providers/src/index.js b/packages/providers/src/index.js index 392ceee2..9d1744a7 100644 --- a/packages/providers/src/index.js +++ b/packages/providers/src/index.js @@ -1,7 +1,16 @@ +import _ from 'lodash-es' import { AliyunDnsProvider } from './dns-provider/aliyun.js' import { DnspodDnsProvider } from './dns-provider/dnspod.js' +import { providerRegistry } from '@certd/api' -export default { +export const DefaultProviders = { AliyunDnsProvider, DnspodDnsProvider } +export default { + install () { + _.forEach(DefaultProviders, item => { + providerRegistry.install(item) + }) + } +}