Files
certd/packages/executor/src/index.js
T

199 lines
5.9 KiB
JavaScript
Raw Normal View History

2020-12-21 00:32:17 +08:00
import { Certd } from '@certd/certd'
import DefaultPlugins from '@certd/plugins'
2021-01-06 23:29:10 +08:00
import { util } from '@certd/api'
import _ from 'lodash-es'
2021-01-02 02:47:58 +08:00
import dayjs from 'dayjs'
import { Trace } from './trace.js'
2021-01-06 23:29:10 +08:00
const logger = util.logger
2021-01-08 15:39:23 +08:00
function createDefaultOptions () {
return {
args: {
forceCert: false,
forceDeploy: true,
2021-01-08 16:59:53 +08:00
forceRedeploy: false,
doNotThrowError: false // 部署流程执行有错误时,不抛异常,此时整个任务执行完毕后,可以返回结果,你可以在返回结果中处理
2021-01-08 15:39:23 +08:00
}
}
}
2020-12-21 00:32:17 +08:00
export class Executor {
2021-01-08 15:39:23 +08:00
constructor () {
2021-01-02 02:47:58 +08:00
this.usePlugins(DefaultPlugins)
this.trace = new Trace()
2020-12-21 00:32:17 +08:00
}
2021-01-14 23:04:47 +08:00
useProviders (providers) {
if (providers) {
_.forEach(item => {
Certd.use(item)
})
}
}
useProvider (provider) {
Certd.use(provider)
}
usePlugin (plugin) {
2020-12-21 00:32:17 +08:00
if (plugin == null) {
return
}
2021-01-08 15:56:50 +08:00
if (this.plugins == null) {
this.plugins = {}
}
2020-12-21 00:32:17 +08:00
this.plugins[plugin.name] = plugin
if (plugin.define) {
const define = plugin.define()
this.plugins[define.name] = plugin
}
}
2021-01-02 02:47:58 +08:00
usePlugins (plugins) {
if (plugins) {
2021-01-14 23:04:47 +08:00
_.forEach(plugins, item => {
this.usePlugin(item)
})
2020-12-21 00:32:17 +08:00
}
}
2021-01-08 15:39:23 +08:00
async run (options) {
2021-01-07 18:05:38 +08:00
logger.info('------------------- Cert-D ---------------------')
2020-12-22 22:47:07 +08:00
try {
2021-01-08 15:39:23 +08:00
options = _.merge(createDefaultOptions(), options)
return await this.doRun(options)
2020-12-22 22:47:07 +08:00
} catch (e) {
logger.error('任务执行出错:', e)
throw e
}
}
async doRun (options) {
// 申请证书
2020-12-21 00:32:17 +08:00
logger.info('任务开始')
2021-01-14 23:04:47 +08:00
const certd = new Certd(options, this.providers)
2021-01-02 02:47:58 +08:00
const cert = await this.runCertd(certd)
2020-12-21 00:32:17 +08:00
if (cert == null) {
throw new Error('申请证书失败')
}
logger.info('证书保存路径:', cert.certDir)
logger.info('----------------------')
2020-12-21 00:32:17 +08:00
if (!cert.isNew) {
// 如果没有更新
if (!options.args?.forceDeploy && !options.args?.forceRedeploy) {
2020-12-21 00:32:17 +08:00
// 且不需要强制运行deploy
logger.info('证书无更新,无需重新部署')
logger.info('任务完成')
return { cert }
}
}
// 读取上次执行进度
2021-01-08 15:39:23 +08:00
let context = {}
2021-01-02 02:47:58 +08:00
const contextJson = await certd.certStore.getCurrentFile('context.json')
if (contextJson) {
context = JSON.parse(contextJson)
}
2021-01-08 15:39:23 +08:00
context.certIsNew = !!cert.isNew
const trace = new Trace(context)
2021-01-08 16:59:53 +08:00
const resultTrace = trace.getInstance({ type: 'result' })
// 运行部署任务
2021-01-02 02:47:58 +08:00
try {
await this.runDeploys({ options, cert, context, trace })
2021-01-02 02:47:58 +08:00
} finally {
await certd.certStore.setCurrentFile('context.json', JSON.stringify(context))
}
2020-12-21 00:32:17 +08:00
logger.info('任务完成')
trace.print()
2021-01-08 16:59:53 +08:00
const result = resultTrace.get({ })
2021-01-08 15:39:23 +08:00
const returnData = {
2020-12-21 00:32:17 +08:00
cert,
2021-01-08 15:39:23 +08:00
context,
result
}
2021-01-08 16:59:53 +08:00
if (result.status === 'error' && options.args.doNotThrowError === false) {
throw new Error(result.remark)
2020-12-21 00:32:17 +08:00
}
2021-01-08 15:39:23 +08:00
return returnData
2020-12-21 00:32:17 +08:00
}
2021-01-02 02:47:58 +08:00
async runCertd (certd) {
logger.info(`证书任务 ${JSON.stringify(certd.options.cert.domains)} 开始`)
2021-01-02 02:47:58 +08:00
const cert = await certd.certApply()
logger.info(`证书任务 ${JSON.stringify(certd.options.cert.domains)} 完成`)
2020-12-21 00:32:17 +08:00
return cert
}
async runDeploys ({ options, cert, context, trace }) {
2020-12-21 00:32:17 +08:00
if (cert == null) {
2021-01-02 02:47:58 +08:00
const certd = new Certd(options)
cert = await certd.readCurrentCert()
2020-12-21 00:32:17 +08:00
}
logger.info('部署任务开始')
2020-12-21 00:32:17 +08:00
for (const deploy of options.deploy) {
const deployName = deploy.deployName
logger.info(`------------【${deployName}】-----------`)
2021-01-08 16:59:53 +08:00
const deployTrace = trace.getInstance({ type: 'deploy', deployName })
2020-12-21 00:32:17 +08:00
if (deploy.disabled === true) {
logger.info('此流程已被禁用,跳过')
logger.info('')
2021-01-08 16:59:53 +08:00
deployTrace.set({ value: { current: 'skip', status: 'disabled', remark: '流程禁用' } })
2021-01-02 02:47:58 +08:00
continue
2020-12-21 00:32:17 +08:00
}
try {
for (const task of deploy.tasks) {
if (context[deployName] == null) {
context[deployName] = {}
}
const taskContext = context[deployName]
2021-01-08 16:59:53 +08:00
// 开始执行任务列表
await this.runTask({ options, cert, task, context: taskContext, deploy, trace })
}
2021-01-08 16:59:53 +08:00
deployTrace.set({ value: { status: 'success', remark: '执行成功' } })
} catch (e) {
2021-01-08 16:59:53 +08:00
deployTrace.set({ value: { status: 'error', remark: '执行失败:' + e.message } })
trace.set({ type: 'result', value: { status: 'error', remark: deployName + '执行失败:' + e.message } })
logger.error('流程执行失败', e)
2020-12-21 00:32:17 +08:00
}
logger.info('')
2020-12-21 00:32:17 +08:00
}
}
async runTask ({ options, task, cert, context, deploy, trace }) {
2020-12-21 00:32:17 +08:00
const taskType = task.type
const Plugin = this.plugins[taskType]
const deployName = deploy.deployName
const taskName = task.taskName
2020-12-21 00:32:17 +08:00
if (Plugin == null) {
throw new Error(`插件:${taskType}还未安装`)
2020-12-21 00:32:17 +08:00
}
let instance = Plugin
if (Plugin instanceof Function) {
instance = new Plugin({ accessProviders: options.accessProviders })
2020-12-21 00:32:17 +08:00
}
2021-01-08 16:59:53 +08:00
const taskTrace = trace.getInstance({ type: 'deploy', deployName, taskName })
const traceStatus = taskTrace.get({})
if (traceStatus?.status === 'success' && !options?.args?.forceRedeploy) {
logger.info(`----【${taskName}】已经执行完成,跳过此任务`)
2021-01-08 16:59:53 +08:00
taskTrace.set({ value: { current: 'skip', status: 'success', remark: '已执行成功过,本次跳过' } })
2021-01-02 02:47:58 +08:00
return
}
logger.info(`----【${taskName}】开始执行`)
2021-01-08 09:13:29 +08:00
try {
2021-01-08 16:59:53 +08:00
// 执行任务
2021-01-08 09:13:29 +08:00
await instance.execute({ cert, props: task.props, context })
2021-01-08 16:59:53 +08:00
taskTrace.set({ value: { current: 'success', status: 'success', remark: '执行成功', time: dayjs().format() } })
2021-01-08 09:13:29 +08:00
} catch (e) {
2021-01-08 16:59:53 +08:00
taskTrace.set({ value: { current: 'error', status: 'error', remark: e.message, time: dayjs().format() } })
2021-01-08 09:13:29 +08:00
throw e
}
logger.info(`----任务【${taskName}】执行完成`)
logger.info('')
2020-12-21 00:32:17 +08:00
}
}