perf: 抽取api

master
xiaojunnuo 2021-01-06 23:29:10 +08:00
parent f07ce6f47d
commit 5312c11472
41 changed files with 5001 additions and 119 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ out
gen
node_modules/
/test/*.private.*
/*.log

14
packages/api/.eslintrc Normal file
View File

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

2468
packages/api/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
packages/api/package.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "@certd/api",
"version": "0.1.2",
"description": "",
"main": "./src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"type": "module",
"author": "Greper",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20",
"log4js": "^6.3.0",
"qs": "^6.9.4"
},
"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"
}
}

View File

@ -1,5 +1,10 @@
import _ from 'lodash'
export class DnsProvider {
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 方法')
}

View File

@ -0,0 +1,4 @@
export { AbstractDnsProvider } from './dns-provider/index.js'
export { Store } from './store/store.js'
export { util } from './utils/index.js'
export { AbstractPlugin } from './plugin/index.js'

View File

@ -0,0 +1,7 @@
import logger from './util.log.js'
import path from './util.path.js'
import { request } from './util.request.js'
import sleep from './util.sleep.js'
export const util = {
logger, path, request, sleep
}

View File

@ -10,16 +10,12 @@
"author": "Greper",
"license": "MIT",
"dependencies": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.2",
"@certd/providers": "^0.1.2",
"@certd/acme-client": "^0.1.1",
"@types/node": "^14.14.13",
"axios": "^0.21.1",
"dayjs": "^1.9.7",
"lodash": "^4.17.20",
"log4js": "^6.3.0",
"node-forge": "^0.10.0",
"qs": "^6.9.4",
"tencentcloud-sdk-nodejs": "^4.0.44"
"lodash-es": "^4.17.20"
},
"devDependencies": {
"chai": "^4.2.0",

View File

@ -1,6 +1,7 @@
import log from './utils/util.log.js'
import acme from '@certd/acme-client'
import _ from 'lodash'
import _ from 'lodash-es'
import { util } from '@certd/api'
const logger = util.logger
export class AcmeService {
constructor (store) {
this.store = store
@ -57,27 +58,27 @@ export class AcmeService {
}
async challengeCreateFn (authz, challenge, keyAuthorization, dnsProvider) {
log.info('Triggered challengeCreateFn()')
logger.info('Triggered challengeCreateFn()')
/* http-01 */
if (challenge.type === 'http-01') {
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`
const fileContents = keyAuthorization
log.info(`Creating challenge response for ${authz.identifier.value} at path: ${filePath}`)
logger.info(`Creating challenge response for ${authz.identifier.value} at path: ${filePath}`)
/* Replace this */
log.info(`Would write "${fileContents}" to path "${filePath}"`)
logger.info(`Would write "${fileContents}" to path "${filePath}"`)
// await fs.writeFileAsync(filePath, fileContents);
} else if (challenge.type === 'dns-01') {
/* dns-01 */
const dnsRecord = `_acme-challenge.${authz.identifier.value}`
const recordValue = keyAuthorization
log.info(`Creating TXT record for ${authz.identifier.value}: ${dnsRecord}`)
logger.info(`Creating TXT record for ${authz.identifier.value}: ${dnsRecord}`)
/* Replace this */
log.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`)
logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`)
return await dnsProvider.createRecord({
fullRecord: dnsRecord,
@ -99,25 +100,25 @@ export class AcmeService {
*/
async challengeRemoveFn (authz, challenge, keyAuthorization, recordItem, dnsProvider) {
log.info('Triggered challengeRemoveFn()')
logger.info('Triggered challengeRemoveFn()')
/* http-01 */
if (challenge.type === 'http-01') {
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`
log.info(`Removing challenge response for ${authz.identifier.value} at path: ${filePath}`)
logger.info(`Removing challenge response for ${authz.identifier.value} at path: ${filePath}`)
/* Replace this */
log.info(`Would remove file on path "${filePath}"`)
logger.info(`Would remove file on path "${filePath}"`)
// await fs.unlinkAsync(filePath);
} else if (challenge.type === 'dns-01') {
const dnsRecord = `_acme-challenge.${authz.identifier.value}`
const recordValue = keyAuthorization
log.info(`Removing TXT record for ${authz.identifier.value}: ${dnsRecord}`)
logger.info(`Removing TXT record for ${authz.identifier.value}: ${dnsRecord}`)
/* Replace this */
log.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`)
logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`)
await dnsProvider.removeRecord({
fullRecord: dnsRecord,
type: 'TXT',
@ -170,13 +171,13 @@ export class AcmeService {
accountUrl = client.getAccountUrl()
this.setAccountUrl(email, accountUrl)
} catch (e) {
log.warn('保存accountUrl出错', e)
logger.warn('保存accountUrl出错', e)
}
}
/* Done */
log.debug(`CSR:\n${csr.toString()}`)
log.debug(`Certificate:\n${crt.toString()}`)
log.info('证书申请成功')
logger.debug(`CSR:\n${csr.toString()}`)
logger.debug(`Certificate:\n${crt.toString()}`)
logger.info('证书申请成功')
return { key, crt, csr }
}

View File

@ -1,12 +1,11 @@
import logger from './utils/util.log.js'
import { util, Store } from '@certd/api'
import { AcmeService } from './acme.js'
import { FileStore } from './store/impl/file-store.js'
import { Store } from './store/store.js'
import { FileStore } from './store/file-store.js'
import { CertStore } from './store/cert-store.js'
import { DnsProviderFactory } from './dns-provider/dns-provider-factory.js'
import { DnsProviderFactory } from '@certd/providers'
import dayjs from 'dayjs'
import forge from 'node-forge'
const logger = util.logger
export class Certd {
constructor (options) {
this.options = options

View File

@ -1,9 +1,7 @@
import { Store } from '../store.js'
import util from '../../utils/util.js'
import { Store, util } from '@certd/api'
import path from 'path'
import fs from 'fs'
import logger from '../../utils/util.log.js'
const logger = util.logger
export class FileStore extends Store {
constructor (opts) {
super()

View File

@ -0,0 +1,18 @@
import pkg from 'chai'
import { createOptions } from '../../../../test/options.js'
import { Certd } from '../../src/index.js'
const { expect } = pkg
describe('AliyunDnsProvider', function () {
it('#申请证书-aliyun', async function () {
this.timeout(300000)
const options = createOptions()
options.args = { forceCert: true, test: false }
const certd = new Certd(options)
const cert = await certd.certApply()
expect(cert).ok
expect(cert.crt).ok
expect(cert.key).ok
expect(cert.detail).ok
expect(cert.expires).ok
})
})

View File

@ -0,0 +1,20 @@
import pkg from 'chai'
import { Certd } from '../../src/index.js'
import { createOptions } from '../../../../test/options.js'
const { expect } = pkg
describe('DnspodDnsProvider', function () {
it('#申请证书', async function () {
this.timeout(300000)
const options = createOptions()
options.cert.domains = ['*.certd.xyz', '*.test.certd.xyz', '*.base.certd.xyz', 'certd.xyz']
options.cert.dnsProvider = 'dnspod'
options.args = { forceCert: true }
const certd = new Certd(options)
const cert = await certd.certApply()
expect(cert).ok
expect(cert.crt).ok
expect(cert.key).ok
expect(cert.detail).ok
expect(cert.expires).ok
})
})

View File

@ -33,7 +33,6 @@ jrunq0tNHR/EKG0ITPLf+6P7MxbmpYNnq918766l0tKsW8oo8ZSGEwKU2LMaSiAa
hasyl/2gMnYXjtKOjDcnR8oLpbrOg0qpVbynmJin1HP835oHPPAZ1gLsqYTTizNz
AHxTaXliTVvS83dogw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEqzCCApOgAwIBAgIRAIvhKg5ZRO08VGQx8JdhT+UwDQYJKoZIhvcNAQELBQAw
GjEYMBYGA1UEAwwPRmFrZSBMRSBSb290IFgxMB4XDTE2MDUyMzIyMDc1OVoXDTM2

View File

@ -13,10 +13,7 @@
"dependencies": {
"@certd/certd": "^0.1.2",
"@certd/plugins": "^0.1.2",
"@types/node": "^14.14.13",
"dayjs": "^1.9.8",
"lodash": "^4.17.20",
"log4js": "^6.3.0"
"lodash-es": "^4.17.20"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",

View File

@ -1,9 +1,10 @@
import { Certd } from '@certd/certd'
import DefaultPlugins from '@certd/plugins'
import logger from './util.log.js'
import _ from 'lodash'
import { util } from '@certd/api'
import _ from 'lodash-es'
import dayjs from 'dayjs'
import { Trace } from './trace.js'
const logger = util.logger
export class Executor {
constructor (args = {}) {
const { plugins } = args

View File

@ -1,5 +1,6 @@
import logger from './util.log.js'
import _ from 'lodash'
import { util } from '@certd/api'
import _ from 'lodash-es'
const logger = util.logger
export class Trace {
constructor (context) {
this.context = context

View File

@ -1,16 +0,0 @@
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')
// }

@ -1 +1 @@
Subproject commit 48fa8732775f0d72e1f361e993900a393d65c898
Subproject commit ea59051a9fab203b0ed102c779dadad0364eba8d

View File

@ -11,10 +11,8 @@
"@alicloud/pop-core": "^1.7.10",
"@certd/certd": "^0.1.1",
"@types/node": "^14.14.13",
"dayjs": "^1.9.7",
"kubernetes-client": "^9.0.0",
"lodash": "^4.17.20",
"log4js": "^6.3.0",
"lodash-es": "^4.17.20",
"ssh2": "^0.8.9",
"tencentcloud-sdk-nodejs": "^4.0.44"
},

View File

@ -1,4 +1,4 @@
import { AbstractPlugin } from '../abstract-plugin/index.js'
import { AbstractPlugin } from '@certd/api'
export class AbstractAliyunPlugin extends AbstractPlugin {
checkRet (ret) {

View File

@ -1,4 +1,4 @@
import { AbstractPlugin } from '../abstract-plugin/index.js'
import { AbstractPlugin } from '@certd/api'
export class AbstractHostPlugin extends AbstractPlugin {
checkRet (ret) {

View File

@ -1,4 +1,4 @@
import { AbstractPlugin } from '../abstract-plugin/index.js'
import { AbstractPlugin } from '@certd/api'
export class AbstractTencentPlugin extends AbstractPlugin {
checkRet (ret) {

View File

@ -1,7 +1,8 @@
import kubernetesClient from 'kubernetes-client'
import logger from './util.log.js'
import { util } from '@certd/api0'
import Request from 'kubernetes-client/backends/request/index.js'
const { KubeConfig, Client } = kubernetesClient
const logger = util.logger
export class K8sClient {
constructor (kubeConfigStr) {
const kubeconfig = new KubeConfig()

View File

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

View File

@ -1,7 +0,0 @@
export default function (timeout) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, timeout)
})
}

View File

@ -1,4 +1,4 @@
import _ from 'lodash'
import _ from 'lodash-es'
import optionsPrivate from '../../../test/options.private.mjs'
const defaultOptions = {
version: '1.0.0',

View File

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

2346
packages/providers/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
{
"name": "@certd/providers",
"version": "0.1.2",
"description": "",
"main": "./src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"type": "module",
"author": "Greper",
"license": "MIT",
"dependencies": {
"@certd/api": "^0.1.2"
},
"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"
}
}

View File

@ -1,8 +1,7 @@
import { DnsProvider } from '../dns-provider.js'
import _ from 'lodash'
import log from '../../utils/util.log.js'
import { request } from '../../utils/util.request.js'
export default class DnspodDnsProvider extends DnsProvider {
import { AbstractDnsProvider, util } from '@certd/api'
import _ from 'lodash-es'
const request = util.request
export default class DnspodDnsProvider extends AbstractDnsProvider {
constructor (dnsProviderConfig) {
super()
if (!dnsProviderConfig.id || !dnsProviderConfig.token) {
@ -35,12 +34,12 @@ export default class DnspodDnsProvider extends DnsProvider {
const ret = await this.doRequest({
url: 'https://dnsapi.cn/Domain.List'
})
log.debug('dnspod 域名列表:', ret.domains)
this.logger.debug('dnspod 域名列表:', ret.domains)
return ret.domains
}
async createRecord ({ fullRecord, type, value }) {
log.info('添加域名解析:', fullRecord, value)
this.logger.info('添加域名解析:', fullRecord, value)
const domainItem = await this.matchDomain(fullRecord, 'name')
const domain = domainItem.name
const rr = fullRecord.replace('.' + domain, '')
@ -56,7 +55,7 @@ export default class DnspodDnsProvider extends DnsProvider {
mx: 1
}
})
log.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record))
this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record))
return ret.record
}
@ -70,7 +69,7 @@ export default class DnspodDnsProvider extends DnsProvider {
record_id: record.id
}
})
log.info('删除域名解析成功:', fullRecord, value)
this.logger.info('删除域名解析成功:', fullRecord, value)
return ret.RecordId
}
}

View File

@ -0,0 +1 @@
export { DnsProviderFactory } from './dns-provider/dns-provider-factory'

View File

@ -31,17 +31,4 @@ describe('AliyunDnsProvider', function () {
console.log('recordId', recordId)
expect(recordId != null).ok
})
it('#申请证书-aliyun', async function () {
this.timeout(300000)
const options = createOptions()
options.args = { forceCert: true, test: false }
const certd = new Certd(options)
const cert = await certd.certApply()
expect(cert).ok
expect(cert.crt).ok
expect(cert.key).ok
expect(cert.detail).ok
expect(cert.expires).ok
})
})

View File

@ -21,19 +21,4 @@ describe('DnspodDnsProvider', function () {
await dnsProvider.removeRecord({ fullRecord: '___certd___.__test__.certd.xyz', type: 'TXT', value: 'aaaa', record })
})
it('#申请证书', async function () {
this.timeout(300000)
const options = createOptions()
options.cert.domains = ['*.certd.xyz', '*.test.certd.xyz', '*.base.certd.xyz']
options.cert.dnsProvider = 'dnspod'
options.args = { forceCert: true }
const certd = new Certd(options)
const cert = await certd.certApply()
expect(cert).ok
expect(cert.crt).ok
expect(cert.key).ok
expect(cert.detail).ok
expect(cert.expires).ok
})
})