feat: 自动化流程

This commit is contained in:
xiaojunnuo
2020-12-21 00:32:17 +08:00
parent e84f5e8b0a
commit 6529fd2fdb
27 changed files with 343 additions and 184 deletions

View File

@@ -0,0 +1,14 @@
{
"extends": "standard",
"env": {
"mocha": true
},
"overrides": [
{
"files": ["*.test.js", "*.spec.js"],
"rules": {
"no-unused-expressions": "off"
}
}
]
}

2359
packages/executor/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
{
"name": "@certd/executor",
"version": "0.0.1",
"description": "",
"main": "./src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"type": "module",
"dependencies": {
"@alicloud/pop-core": "^1.7.10",
"@types/node": "^14.14.13",
"lodash": "^4.17.20",
"log4js": "^6.3.0",
"@certd/certd": "^0.0.1",
"@certd/plugins": "^0.0.1"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"mocha": "^8.2.1"
},
"author": "Greper",
"license": "MIT"
}

View File

@@ -0,0 +1,103 @@
import { Certd } from '@certd/certd'
import DefaultPlugins from '@certd/plugins'
import logger from './util.log.js'
import _ from 'lodash'
export class Executor {
constructor (args = {}) {
this.certd = new Certd()
const { plugins } = args
this.initPlugins(plugins)
}
use (plugin) {
if (plugin == null) {
return
}
this.plugins[plugin.name] = plugin
if (plugin.define) {
const define = plugin.define()
this.plugins[define.name] = plugin
}
}
initPlugins (customPlugins) {
this.plugins = {}
for (const key in DefaultPlugins) {
this.use(DefaultPlugins[key])
}
if (customPlugins) {
for (const plugin of customPlugins) {
this.use(plugin)
}
}
}
async run (options, args) {
if (args != null) {
_.merge(options.args, args)
}
logger.info('任务开始')
const cert = await this.runCertd(options)
if (cert == null) {
throw new Error('申请证书失败')
}
logger.info('证书保存路径:', cert.certDir)
if (!cert.isNew) {
// 如果没有更新
if (!options.args.forceDeploy) {
// 且不需要强制运行deploy
logger.info('证书无更新,无需重新部署')
logger.info('任务完成')
return { cert }
}
}
const context = {}
await this.runDeploys({ options, cert, context })
logger.info('任务完成')
return {
cert,
context
}
}
async runCertd (options) {
logger.info(`申请证书${JSON.stringify(options.cert.domains)}开始`)
const cert = await this.certd.certApply(options)
logger.info(`申请证书${JSON.stringify(options.cert.domains)}完成`)
return cert
}
async runDeploys ({ options, cert, context }) {
if (cert == null) {
cert = this.certd.readCurrentCert(options.cert.email, options.cert.domains)
}
for (const deploy of options.deploy) {
logger.info(`--部署任务【${deploy.name}】开始`)
if (deploy.disabled === true) {
logger.info('----此任务已被禁用,跳过')
break
}
for (const task of deploy.tasks) {
await this.runTask({ options, cert, task, context })
}
logger.info(`--部署任务【${deploy.name}】完成`)
}
}
async runTask ({ options, task, cert, context }) {
const taskType = task.type
const Plugin = this.plugins[taskType]
if (Plugin == null) {
throw new Error(`----插件:${taskType}还未安装`)
}
logger.info(`----任务【${task.name}】开始执行`)
let instance = Plugin
if (Plugin instanceof Function) {
instance = new Plugin()
}
await instance.execute({ cert, accessProviders: options.accessProviders, args: task, context })
logger.info(`----任务【${task.name}】执行完成`)
}
}

View File

@@ -0,0 +1,16 @@
import log4js from 'log4js'
log4js.configure({
appenders: { std: { type: 'stdout' } },
categories: { default: { appenders: ['std'], level: 'info' } }
})
const logger = log4js.getLogger('certd')
export default logger
// import debug from 'debug'
// debug.enable('info,debug,error,warn')
// export default {
// debug: debug('debug'),
// info: debug('info'),
// error: debug('error'),
// warn: debug('warn')
// }

View File

@@ -0,0 +1,25 @@
import pkg from 'chai'
import options from './options.js'
import { Executor } from '../src/index.js'
const { expect } = pkg
describe('AutoDeploy', function () {
it('#run', async function () {
const executor = new Executor()
const ret = await executor.run(options)
expect(ret).ok
expect(ret.cert).ok
})
it('#forceCert', async function () {
const executor = new Executor()
const ret = await executor.run(options, { forceCert: true, forceDeploy: false })
expect(ret).ok
expect(ret.cert).ok
})
it('#forceDeploy', async function () {
const executor = new Executor()
const ret = await executor.run(options, { forceCert: false, forceDeploy: true })
expect(ret).ok
expect(ret.cert).ok
})
})

View File

@@ -0,0 +1,96 @@
import _ from 'lodash'
import optionsPrivate from '../../../test/options.private.mjs'
const defaultOptions = {
args: {
forceCert: false, // 强制更新证书
skipCert: false, // 是否跳过证书申请环节
forceDeploy: false
},
accessProviders: {
aliyun: {
providerType: 'aliyun',
accessKeyId: '',
accessKeySecret: ''
},
myLinux: {
providerType: 'SSH',
username: 'xxx',
password: 'xxx',
host: '1111.com',
port: 22,
publicKey: ''
}
},
cert: {
domains: ['*.docmirror.cn'],
email: 'xiaojunnuo@qq.com',
challenge: {
challengeType: 'dns',
dnsProvider: 'aliyun'
},
csrInfo: {
country: 'CN',
state: 'GuangDong',
locality: 'ShengZhen',
organization: 'CertD Org.',
organizationUnit: 'IT Department',
emailAddress: 'xiaojunnuo@qq.com'
}
},
deploy: [
{
name: '流程1-部署到阿里云系列产品',
tasks: [
{
name: '上传证书到云',
type: 'uploadCertToAliyun',
accessProvider: 'aliyun'
},
{ // CDN、SCDN、DCDN和负载均衡SLB
name: '部署证书到CDN',
type: 'deployCertToAliyunCDN',
domainName: 'certd-cdn-upload.docmirror.cn',
certName: 'certd部署测试(upload)',
certType: 'upload',
accessProvider: 'aliyun'
}
// {
// name: '部署证书到阿里云集群Ingress',
// type: 'deployCertToAliyunK8sIngress',
// accessProvider: 'aliyun'
// }
]
},
{
name: '流程2-部署到nginx服务器',
disabled: true,
tasks: [
{
name: '上传证书到服务器,并重启nginx',
type: 'sshAndExecute',
ssh: 'myLinux',
upload: [
{ from: '{certPath}', to: '/xxx/xxx/xxx.cert.pem' },
{ from: '{keyPath}', to: '/xxx/xxx/xxx.key' }
],
script: 'sudo systemctl restart nginx'
}
]
},
{
deployName: '流程3-触发jenkins任务',
tasks: [
{
name: '触发jenkins任务',
type: 'sshAndExecute',
ssh: 'myLinux',
script: 'sudo systemctl restart nginx'
}
]
}
]
}
_.merge(defaultOptions, optionsPrivate)
export default defaultOptions

View File

@@ -0,0 +1,64 @@
Arguments:
D:\Soft\Development\Nodejs\node.exe C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\bin\yarn.js install
PATH:
D:\Code\certd\certd\node_modules\.bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\libnvvp;D:\Soft\Development\Python3.5.3\Scripts\;D:\Soft\Development\Python3.5.3\;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\lib\x64;C:\Program Files\Anaconda3;C:\Program Files\Anaconda3\Scripts;C:\Program Files\Anaconda3\Library\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\Soft\Development\Zookeeper\bin;D:\Soft\Development\Maven\apache-maven-3.0.3\bin;C:\WINDOWS\System32\OpenSSH\;D:\Soft\Development\Microsoft VS Code\bin;D:\Soft\Development\Redis\;D:\Soft\Development\gradle-4.10.3\bin;D:\Soft\Development\Android\flutter\bin;C:\Program Files (x86)\QT Lite\QTSystem;D:\Soft\Development\java\bin;C:\ProgramData;D:\Soft\Development\nvmnodejs;D:\Soft\Development\Git\cmd;D:\Soft\Development\Go\bin;D:\Code\open\fgit-go\release;D:\Soft\Development\Nodejs\;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;D:\Soft\Development\Microsoft VS Code\bin;D:\Soft\Development\IntelliJ IDEA 2018.3.2\bin;C:\Users\Administrator\AppData\Local\BypassRuntm;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;D:\Soft\Development\IntelliJ IDEA 2020.2\bin;;C:\Users\Administrator\AppData\Local\GitHubDesktop\bin;C:\Users\Administrator\go\bin;D:\Resources\npm\global;D:\Resources\yarn\global;C:\Users\Administrator\AppData\Roaming\npm;
Yarn version:
1.22.10
Node version:
14.15.0
Platform:
win32 x64
Trace:
Error: https://registry.npmjs.org/@certd%2fcertd: Not found
at Request.params.callback [as _callback] (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:66988:18)
at Request.self.callback (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:140662:22)
at Request.emit (events.js:315:20)
at Request.<anonymous> (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:141634:10)
at Request.emit (events.js:315:20)
at IncomingMessage.<anonymous> (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:141556:12)
at Object.onceWrapper (events.js:421:28)
at IncomingMessage.emit (events.js:327:22)
at endReadableNT (_stream_readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
npm manifest:
{
"name": "@certd/samples",
"version": "0.0.1",
"description": "",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"type": "module",
"dependencies": {
"@alicloud/pop-core": "^1.7.10",
"@types/node": "^14.14.13",
"lodash": "^4.17.20",
"log4js": "^6.3.0",
"@certd/certd": "^0.0.1",
"@certd/plugins": "^0.0.1"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"mocha": "^8.2.1"
},
"author": "Greper",
"license": "MIT"
}
yarn manifest:
No manifest
Lockfile:
No lockfile

1790
packages/executor/yarn.lock Normal file

File diff suppressed because it is too large Load Diff