mirror of
https://github.com/certd/certd.git
synced 2025-11-25 09:10:11 +08:00
refactor: move
This commit is contained in:
14
packages/plugins/plugin-tencent/.eslintrc
Normal file
14
packages/plugins/plugin-tencent/.eslintrc
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "standard",
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.js", "*.spec.js"],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
3690
packages/plugins/plugin-tencent/package-lock.json
generated
Normal file
3690
packages/plugins/plugin-tencent/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
packages/plugins/plugin-tencent/package.json
Normal file
26
packages/plugins/plugin-tencent/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@certd/plugins",
|
||||
"version": "0.1.13",
|
||||
"description": "",
|
||||
"main": "src/index.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@certd/api": "^0.1.13",
|
||||
"dayjs": "^1.9.7",
|
||||
"kubernetes-client": "^9.0.0",
|
||||
"lodash-es": "^4.17.20",
|
||||
"tencentcloud-sdk-nodejs": "^4.0.44"
|
||||
},
|
||||
"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",
|
||||
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export class DnspodAccessProvider {
|
||||
static define () {
|
||||
return {
|
||||
name: 'dnspod',
|
||||
label: 'dnspod',
|
||||
desc: '腾讯云的域名解析接口已迁移到dnspod',
|
||||
input: {
|
||||
id: {
|
||||
type: String,
|
||||
component: {
|
||||
placeholder: 'dnspod接口账户id',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
label: 'token',
|
||||
component: {
|
||||
placeholder: '开放接口token',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export class TencentAccessProvider {
|
||||
static define () {
|
||||
return {
|
||||
name: 'tencent',
|
||||
label: '腾讯云',
|
||||
input: {
|
||||
secretId: {
|
||||
type: String,
|
||||
label: 'secretId',
|
||||
component: {
|
||||
placeholder: 'secretId',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
},
|
||||
secretKey: {
|
||||
type: String,
|
||||
label: 'secretKey',
|
||||
component: {
|
||||
placeholder: 'secretKey',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
packages/plugins/plugin-tencent/src/dns-providers/dnspod.js
Normal file
94
packages/plugins/plugin-tencent/src/dns-providers/dnspod.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import { AbstractDnsProvider, util } from '@certd/api'
|
||||
import _ from 'lodash-es'
|
||||
const request = util.request
|
||||
export class DnspodDnsProvider extends AbstractDnsProvider {
|
||||
static define () {
|
||||
return {
|
||||
name: 'dnspod',
|
||||
label: 'dnspod(腾讯云)',
|
||||
desc: '腾讯云的域名解析接口已迁移到dnspod',
|
||||
input: {
|
||||
accessProvider: {
|
||||
label: '授权',
|
||||
type: [String, Object],
|
||||
desc: '需要dnspod类型的授权',
|
||||
component: {
|
||||
name: 'access-provider-selector',
|
||||
filter: 'dnspod'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor (args) {
|
||||
super(args)
|
||||
const { props } = args
|
||||
const accessProvider = this.getAccessProvider(props.accessProvider)
|
||||
this.loginToken = accessProvider.id + ',' + accessProvider.token
|
||||
}
|
||||
|
||||
async doRequest (options) {
|
||||
const config = {
|
||||
method: 'post',
|
||||
formData: {
|
||||
login_token: this.loginToken,
|
||||
format: 'json',
|
||||
lang: 'cn',
|
||||
error_on_empty: 'no'
|
||||
},
|
||||
timeout: 5000
|
||||
}
|
||||
_.merge(config, options)
|
||||
|
||||
const ret = await request(config)
|
||||
if (!ret || !ret.status || ret.status.code !== '1') {
|
||||
throw new Error('请求失败:' + ret.status.message + ',api=' + config.url)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
async getDomainList () {
|
||||
const ret = await this.doRequest({
|
||||
url: 'https://dnsapi.cn/Domain.List'
|
||||
})
|
||||
this.logger.debug('dnspod 域名列表:', ret.domains)
|
||||
return ret.domains
|
||||
}
|
||||
|
||||
async createRecord ({ fullRecord, type, value }) {
|
||||
this.logger.info('添加域名解析:', fullRecord, value)
|
||||
const domainItem = await this.matchDomain(fullRecord, 'name')
|
||||
const domain = domainItem.name
|
||||
const rr = fullRecord.replace('.' + domain, '')
|
||||
|
||||
const ret = await this.doRequest({
|
||||
url: 'https://dnsapi.cn/Record.Create',
|
||||
formData: {
|
||||
domain,
|
||||
sub_domain: rr,
|
||||
record_type: type,
|
||||
record_line: '默认',
|
||||
value: value,
|
||||
mx: 1
|
||||
}
|
||||
})
|
||||
this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record))
|
||||
return ret.record
|
||||
}
|
||||
|
||||
async removeRecord ({ fullRecord, type, value, record }) {
|
||||
const domain = await this.matchDomain(fullRecord, 'name')
|
||||
|
||||
const ret = await this.doRequest({
|
||||
url: 'https://dnsapi.cn/Record.Remove',
|
||||
formData: {
|
||||
domain,
|
||||
record_id: record.id
|
||||
}
|
||||
})
|
||||
this.logger.info('删除域名解析成功:', fullRecord, value)
|
||||
return ret.RecordId
|
||||
}
|
||||
}
|
||||
34
packages/plugins/plugin-tencent/src/index.js
Normal file
34
packages/plugins/plugin-tencent/src/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import _ from 'lodash-es'
|
||||
|
||||
import { TencentAccessProvider } from './access-providers/tencent'
|
||||
import { DnspodAccessProvider } from './access-providers/dnspod'
|
||||
import { DnspodDnsProvider } from './dns-providers/dnspod.js'
|
||||
|
||||
import { UploadCertToTencent } from './plugins/upload-to-tencent'
|
||||
|
||||
import { DeployCertToTencentCDN } from './plugins/deploy-to-cdn'
|
||||
|
||||
import { DeployCertToTencentCLB } from './plugins/deploy-to-clb'
|
||||
|
||||
import { DeployCertToTencentTKEIngress } from './plugins/deploy-to-tke-ingress'
|
||||
|
||||
import { pluginRegistry, accessProviderRegistry, dnsProviderRegistry } from '@certd/api'
|
||||
|
||||
export const DefaultPlugins = {
|
||||
UploadCertToTencent,
|
||||
DeployCertToTencentTKEIngress,
|
||||
DeployCertToTencentCDN,
|
||||
DeployCertToTencentCLB
|
||||
}
|
||||
export default {
|
||||
install () {
|
||||
_.forEach(DefaultPlugins, item => {
|
||||
pluginRegistry.install(item)
|
||||
})
|
||||
|
||||
accessProviderRegistry.install(TencentAccessProvider)
|
||||
accessProviderRegistry.install(DnspodDnsProvider)
|
||||
|
||||
dnsProviderRegistry.install(DnspodDnsProvider)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { AbstractPlugin } from '@certd/api'
|
||||
|
||||
export class AbstractTencentPlugin extends AbstractPlugin {
|
||||
checkRet (ret) {
|
||||
if (!ret || ret.Error) {
|
||||
throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message)
|
||||
}
|
||||
}
|
||||
|
||||
getSafetyDomain (domain) {
|
||||
return domain.replace(/\*/g, '_')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { AbstractTencentPlugin } from '../abstract-tencent.js'
|
||||
import dayjs from 'dayjs'
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs'
|
||||
|
||||
export class DeployCertToTencentCDN extends AbstractTencentPlugin {
|
||||
/**
|
||||
* 插件定义
|
||||
* 名称
|
||||
* 入参
|
||||
* 出参
|
||||
*/
|
||||
static define () {
|
||||
return {
|
||||
name: 'deployCertToTencentCDN',
|
||||
label: '部署到腾讯云CDN',
|
||||
input: {
|
||||
domainName: {
|
||||
label: 'cdn加速域名',
|
||||
required: true
|
||||
},
|
||||
certName: {
|
||||
label: '证书名称',
|
||||
desc: '证书上传后将以此参数作为名称前缀'
|
||||
},
|
||||
certType: {
|
||||
default: 'upload',
|
||||
label: '证书来源',
|
||||
options: [
|
||||
{ value: 'upload', label: '直接上传' },
|
||||
{ value: 'cloud', label: '从证书库', desc: '需要uploadCertToTencent作为前置任务' }
|
||||
],
|
||||
desc: '如果选择‘从证书库’类型,则需要以《上传证书到腾讯云》作为前置任务',
|
||||
required: true
|
||||
},
|
||||
accessProvider: {
|
||||
label: 'Access提供者',
|
||||
type: [String, Object],
|
||||
desc: 'access 授权',
|
||||
component: {
|
||||
name: 'access-provider-selector',
|
||||
filter: 'tencent'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
output: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async execute ({ cert, props, context }) {
|
||||
const accessProvider = this.getAccessProvider(props.accessProvider)
|
||||
const client = this.getClient(accessProvider)
|
||||
const params = this.buildParams(props, context, cert)
|
||||
await this.doRequest(client, params)
|
||||
}
|
||||
|
||||
async rollback ({ cert, props, context }) {
|
||||
|
||||
}
|
||||
|
||||
getClient (accessProvider) {
|
||||
const CdnClient = tencentcloud.cdn.v20180606.Client
|
||||
|
||||
const clientConfig = {
|
||||
credential: {
|
||||
secretId: accessProvider.secretId,
|
||||
secretKey: accessProvider.secretKey
|
||||
},
|
||||
region: '',
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: 'cdn.tencentcloudapi.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CdnClient(clientConfig)
|
||||
}
|
||||
|
||||
buildParams (props, context, cert) {
|
||||
const { domainName, from } = props
|
||||
const { tencentCertId } = context
|
||||
this.logger.info('部署腾讯云证书ID:', tencentCertId)
|
||||
const params = {
|
||||
Https: {
|
||||
Switch: 'on',
|
||||
CertInfo: {
|
||||
CertId: tencentCertId
|
||||
// Certificate: '1231',
|
||||
// PrivateKey: '1231'
|
||||
}
|
||||
},
|
||||
Domain: domainName
|
||||
}
|
||||
if (from === 'upload' || tencentCertId == null) {
|
||||
params.Https.CertInfo = {
|
||||
Certificate: cert.crt,
|
||||
PrivateKey: cert.key
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
async doRequest (client, params) {
|
||||
const ret = await client.UpdateDomainConfig(params)
|
||||
this.checkRet(ret)
|
||||
this.logger.info('设置腾讯云CDN证书成功:', ret.RequestId)
|
||||
return ret.RequestId
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import { AbstractTencentPlugin } from '../abstract-tencent.js'
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs'
|
||||
export class DeployCertToTencentCLB extends AbstractTencentPlugin {
|
||||
/**
|
||||
* 插件定义
|
||||
* 名称
|
||||
* 入参
|
||||
* 出参
|
||||
*/
|
||||
static define () {
|
||||
return {
|
||||
name: 'deployCertToTencentCLB',
|
||||
label: '部署到腾讯云CLB',
|
||||
desc: '暂时只支持单向认证证书,暂时只支持通用负载均衡',
|
||||
input: {
|
||||
region: {
|
||||
label: '大区',
|
||||
default: 'ap-guangzhou',
|
||||
required: true
|
||||
},
|
||||
domain: {
|
||||
label: '域名',
|
||||
type: [String, Array],
|
||||
required: true,
|
||||
desc: '要更新的支持https的负载均衡的域名'
|
||||
},
|
||||
loadBalancerId: {
|
||||
label: '负载均衡ID',
|
||||
desc: '如果没有配置,则根据域名匹配负载均衡下的监听器(根据域名匹配时暂时只支持前100个)',
|
||||
required: true
|
||||
},
|
||||
listenerId: {
|
||||
label: '监听器ID',
|
||||
desc: '如果没有配置,则根据域名或负载均衡id匹配监听器'
|
||||
},
|
||||
certName: {
|
||||
label: '证书名称',
|
||||
desc: '如无uploadCertToTencent作为前置,则此项需要设置,默认为域名'
|
||||
},
|
||||
accessProvider: {
|
||||
label: 'Access提供者',
|
||||
type: [String, Object],
|
||||
desc: 'access授权',
|
||||
component: {
|
||||
name: 'access-provider-selector',
|
||||
filter: 'tencent'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
output: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async execute ({ cert, props, context }) {
|
||||
const accessProvider = this.getAccessProvider(props.accessProvider)
|
||||
const { region } = props
|
||||
const client = this.getClient(accessProvider, region)
|
||||
|
||||
const lastCertId = await this.getCertIdFromProps(client, props)
|
||||
if (!props.domain) {
|
||||
await this.updateListener(client, cert, props, context)
|
||||
} else {
|
||||
await this.updateByDomainAttr(client, cert, props, context)
|
||||
}
|
||||
|
||||
try {
|
||||
await this.sleep(2000)
|
||||
let newCertId = await this.getCertIdFromProps(client, props)
|
||||
if ((lastCertId && newCertId === lastCertId) || (!lastCertId && !newCertId)) {
|
||||
await this.sleep(2000)
|
||||
newCertId = await this.getCertIdFromProps(client, props)
|
||||
}
|
||||
if (newCertId === lastCertId) {
|
||||
return {}
|
||||
}
|
||||
this.logger.info('腾讯云证书ID:', newCertId)
|
||||
if (!context.tencentCertId) {
|
||||
context.tencentCertId = newCertId
|
||||
}
|
||||
return { tencentCertId: newCertId }
|
||||
} catch (e) {
|
||||
this.logger.warn('查询腾讯云证书失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
async getCertIdFromProps (client, props) {
|
||||
const listenerRet = await this.getListenerList(client, props.loadBalancerId, [props.listenerId])
|
||||
return this.getCertIdFromListener(listenerRet[0], props.domain)
|
||||
}
|
||||
|
||||
getCertIdFromListener (listener, domain) {
|
||||
let certId
|
||||
if (!domain) {
|
||||
certId = listener.Certificate.CertId
|
||||
} else {
|
||||
if (listener.Rules && listener.Rules.length > 0) {
|
||||
for (const rule of listener.Rules) {
|
||||
if (rule.Domain === domain) {
|
||||
if (rule.Certificate != null) {
|
||||
certId = rule.Certificate.CertId
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return certId
|
||||
}
|
||||
|
||||
async rollback ({ cert, props, context }) {
|
||||
this.logger.warn('未实现rollback')
|
||||
}
|
||||
|
||||
async updateListener (client, cert, props, context) {
|
||||
const params = this.buildProps(props, context, cert)
|
||||
const ret = await client.ModifyListener(params)
|
||||
this.checkRet(ret)
|
||||
this.logger.info('设置腾讯云CLB证书成功:', ret.RequestId, '->loadBalancerId:', props.loadBalancerId, 'listenerId', props.listenerId)
|
||||
return ret
|
||||
}
|
||||
|
||||
async updateByDomainAttr (client, cert, props, context) {
|
||||
const params = this.buildProps(props, context, cert)
|
||||
params.Domain = props.domain
|
||||
const ret = await client.ModifyDomainAttributes(params)
|
||||
this.checkRet(ret)
|
||||
this.logger.info('设置腾讯云CLB证书(sni)成功:', ret.RequestId, '->loadBalancerId:', props.loadBalancerId, 'listenerId', props.listenerId, 'domain:', props.domain)
|
||||
return ret
|
||||
}
|
||||
|
||||
buildProps (props, context, cert) {
|
||||
const { certName } = props
|
||||
const { tencentCertId } = context
|
||||
this.logger.info('部署腾讯云证书ID:', tencentCertId)
|
||||
const params = {
|
||||
Certificate: {
|
||||
SSLMode: 'UNIDIRECTIONAL', // 单向认证
|
||||
CertId: tencentCertId
|
||||
},
|
||||
LoadBalancerId: props.loadBalancerId,
|
||||
ListenerId: props.listenerId
|
||||
}
|
||||
|
||||
if (tencentCertId == null) {
|
||||
params.Certificate.CertName = this.appendTimeSuffix(certName || cert.domain)
|
||||
params.Certificate.CertKey = cert.key
|
||||
params.Certificate.CertContent = cert.crt
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
async getCLBList (client, props) {
|
||||
const params = {
|
||||
Limit: 100, // 最大暂时只支持100个,暂时没做翻页
|
||||
OrderBy: 'CreateTime',
|
||||
OrderType: 0,
|
||||
...props.DescribeLoadBalancers
|
||||
}
|
||||
const ret = await client.DescribeLoadBalancers(params)
|
||||
this.checkRet(ret)
|
||||
return ret.LoadBalancerSet
|
||||
}
|
||||
|
||||
async getListenerList (client, balancerId, listenerIds) {
|
||||
// HTTPS
|
||||
const params = {
|
||||
LoadBalancerId: balancerId,
|
||||
Protocol: 'HTTPS',
|
||||
ListenerIds: listenerIds
|
||||
}
|
||||
const ret = await client.DescribeListeners(params)
|
||||
this.checkRet(ret)
|
||||
return ret.Listeners
|
||||
}
|
||||
|
||||
getClient (accessProvider, region) {
|
||||
const ClbClient = tencentcloud.clb.v20180317.Client
|
||||
|
||||
const clientConfig = {
|
||||
credential: {
|
||||
secretId: accessProvider.secretId,
|
||||
secretKey: accessProvider.secretKey
|
||||
},
|
||||
region: region,
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: 'clb.tencentcloudapi.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ClbClient(clientConfig)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import { AbstractTencentPlugin } from '../abstract-tencent.js'
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs'
|
||||
import { K8sClient } from '../../utils/util.k8s.client.js'
|
||||
export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
||||
/**
|
||||
* 插件定义
|
||||
* 名称
|
||||
* 入参
|
||||
* 出参
|
||||
*/
|
||||
static define () {
|
||||
return {
|
||||
name: 'deployCertToTencentTKEIngress',
|
||||
label: '部署到腾讯云TKE-ingress',
|
||||
desc: '需要【上传到腾讯云】作为前置任务',
|
||||
input: {
|
||||
region: {
|
||||
label: '大区',
|
||||
default: 'ap-guangzhou',
|
||||
required: true
|
||||
},
|
||||
clusterId: {
|
||||
label: '集群ID',
|
||||
required: true,
|
||||
desc: '例如:cls-6lbj1vee',
|
||||
request: true
|
||||
},
|
||||
namespace: {
|
||||
label: '集群namespace',
|
||||
default: 'default',
|
||||
required: true
|
||||
},
|
||||
secreteName: {
|
||||
type: [String, Array],
|
||||
label: '证书的secret名称',
|
||||
desc: '支持多个(传入数组)',
|
||||
required: true
|
||||
},
|
||||
ingressName: {
|
||||
type: [String, Array],
|
||||
label: 'ingress名称',
|
||||
desc: '支持多个(传入数组)'
|
||||
},
|
||||
clusterIp: {
|
||||
type: String,
|
||||
label: '集群内网ip',
|
||||
desc: '如果开启了外网的话,无需设置'
|
||||
},
|
||||
clusterDomain: {
|
||||
type: String,
|
||||
label: '集群域名',
|
||||
desc: '可不填,默认为:[clusterId].ccs.tencent-cloud.com'
|
||||
},
|
||||
/**
|
||||
* AccessProvider的key,或者一个包含access的具体的对象
|
||||
*/
|
||||
accessProvider: {
|
||||
label: 'Access授权',
|
||||
type: [String, Object],
|
||||
desc: 'access授权',
|
||||
component: {
|
||||
name: 'access-provider-selector',
|
||||
filter: 'tencent'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
output: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async execute ({ cert, props, context }) {
|
||||
const accessProvider = this.getAccessProvider(props.accessProvider)
|
||||
const tkeClient = this.getTkeClient(accessProvider, props.region)
|
||||
const kubeConfigStr = await this.getTkeKubeConfig(tkeClient, props.clusterId)
|
||||
|
||||
this.logger.info('kubeconfig已成功获取')
|
||||
const k8sClient = new K8sClient(kubeConfigStr)
|
||||
if (props.clusterIp != null) {
|
||||
let clusterDomain = props.clusterDomain
|
||||
if (!clusterDomain) {
|
||||
clusterDomain = `${props.clusterId}.ccs.tencent-cloud.com`
|
||||
}
|
||||
// 修改内网解析ip地址
|
||||
k8sClient.setLookup({ [clusterDomain]: { ip: props.clusterIp } })
|
||||
}
|
||||
await this.patchCertSecret({ k8sClient, props, context })
|
||||
await this.sleep(2000) // 停留2秒,等待secret部署完成
|
||||
await this.restartIngress({ k8sClient, props })
|
||||
return true
|
||||
}
|
||||
|
||||
getTkeClient (accessProvider, region = 'ap-guangzhou') {
|
||||
const TkeClient = tencentcloud.tke.v20180525.Client
|
||||
const clientConfig = {
|
||||
credential: {
|
||||
secretId: accessProvider.secretId,
|
||||
secretKey: accessProvider.secretKey
|
||||
},
|
||||
region,
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: 'tke.tencentcloudapi.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new TkeClient(clientConfig)
|
||||
}
|
||||
|
||||
async getTkeKubeConfig (client, clusterId) {
|
||||
// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher
|
||||
const params = {
|
||||
ClusterId: clusterId
|
||||
}
|
||||
const ret = await client.DescribeClusterKubeconfig(params)
|
||||
this.checkRet(ret)
|
||||
this.logger.info('注意:后续操作需要在【集群->基本信息】中开启外网或内网访问,https://console.cloud.tencent.com/tke2/cluster')
|
||||
return ret.Kubeconfig
|
||||
}
|
||||
|
||||
async patchCertSecret ({ k8sClient, props, context }) {
|
||||
const { tencentCertId } = context
|
||||
if (tencentCertId == null) {
|
||||
throw new Error('请先将【上传证书到腾讯云】作为前置任务')
|
||||
}
|
||||
this.logger.info('腾讯云证书ID:', tencentCertId)
|
||||
const certIdBase64 = Buffer.from(tencentCertId).toString('base64')
|
||||
|
||||
const { namespace, secretName } = props
|
||||
|
||||
const body = {
|
||||
data: {
|
||||
qcloud_cert_id: certIdBase64
|
||||
},
|
||||
metadata: {
|
||||
labels: {
|
||||
certd: this.appendTimeSuffix('certd')
|
||||
}
|
||||
}
|
||||
}
|
||||
let secretNames = secretName
|
||||
if (typeof secretName === 'string') {
|
||||
secretNames = [secretName]
|
||||
}
|
||||
for (const secret of secretNames) {
|
||||
await k8sClient.patchSecret({ namespace, secretName: secret, body })
|
||||
this.logger.info(`CertSecret已更新:${secret}`)
|
||||
}
|
||||
}
|
||||
|
||||
async restartIngress ({ k8sClient, props }) {
|
||||
const { namespace, ingressName } = props
|
||||
|
||||
const body = {
|
||||
metadata: {
|
||||
labels: {
|
||||
certd: this.appendTimeSuffix('certd')
|
||||
}
|
||||
}
|
||||
}
|
||||
let ingressNames = ingressName
|
||||
if (typeof ingressName === 'string') {
|
||||
ingressNames = [ingressName]
|
||||
}
|
||||
for (const ingress of ingressNames) {
|
||||
await k8sClient.patchIngress({ namespace, ingressName: ingress, body })
|
||||
this.logger.info(`ingress已重启:${ingress}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs'
|
||||
import { AbstractTencentPlugin } from '../abstract-tencent.js'
|
||||
|
||||
export class UploadCertToTencent extends AbstractTencentPlugin {
|
||||
/**
|
||||
* 插件定义
|
||||
* 名称
|
||||
* 入参
|
||||
* 出参
|
||||
*/
|
||||
static define () {
|
||||
return {
|
||||
name: 'uploadCertToTencent',
|
||||
label: '上传证书到腾讯云',
|
||||
input: {
|
||||
name: {
|
||||
label: '证书名称'
|
||||
},
|
||||
accessProvider: {
|
||||
label: 'Access授权',
|
||||
type: [String, Object],
|
||||
desc: 'access授权',
|
||||
component: {
|
||||
name: 'access-provider-selector',
|
||||
filter: 'tencent'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
output: {
|
||||
tencentCertId: {
|
||||
type: String,
|
||||
desc: '上传成功后的腾讯云CertId'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getClient (accessProvider) {
|
||||
const SslClient = tencentcloud.ssl.v20191205.Client
|
||||
|
||||
const clientConfig = {
|
||||
credential: {
|
||||
secretId: accessProvider.secretId,
|
||||
secretKey: accessProvider.secretKey
|
||||
},
|
||||
region: '',
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: 'ssl.tencentcloudapi.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new SslClient(clientConfig)
|
||||
}
|
||||
|
||||
async execute ({ cert, props, context, logger }) {
|
||||
const { name, accessProvider } = props
|
||||
const certName = this.appendTimeSuffix(name || cert.domain)
|
||||
|
||||
const provider = this.getAccessProvider(accessProvider)
|
||||
const client = this.getClient(provider)
|
||||
|
||||
const params = {
|
||||
CertificatePublicKey: cert.crt,
|
||||
CertificatePrivateKey: cert.key,
|
||||
Alias: certName
|
||||
}
|
||||
const ret = await client.UploadCertificate(params)
|
||||
this.checkRet(ret)
|
||||
this.logger.info('证书上传成功:tencentCertId=', ret.CertificateId)
|
||||
context.tencentCertId = ret.CertificateId
|
||||
}
|
||||
|
||||
async rollback ({ cert, props, context }) {
|
||||
const { accessProvider } = props
|
||||
const provider = super.getAccessProvider(accessProvider)
|
||||
const client = this.getClient(provider)
|
||||
|
||||
const { tencentCertId } = context
|
||||
const params = {
|
||||
CertificateId: tencentCertId
|
||||
}
|
||||
const ret = await client.DeleteCertificate(params)
|
||||
this.checkRet(ret)
|
||||
this.logger.info('证书删除成功:DeleteResult=', ret.DeleteResult)
|
||||
delete context.tencentCertId
|
||||
}
|
||||
}
|
||||
109
packages/plugins/plugin-tencent/src/utils/util.k8s.client.js
Normal file
109
packages/plugins/plugin-tencent/src/utils/util.k8s.client.js
Normal file
@@ -0,0 +1,109 @@
|
||||
import kubernetesClient from 'kubernetes-client'
|
||||
import { util } from '@certd/api'
|
||||
import Request from 'kubernetes-client/backends/request/index.js'
|
||||
import dns from 'dns'
|
||||
const { KubeConfig, Client } = kubernetesClient
|
||||
const logger = util.logger
|
||||
|
||||
export class K8sClient {
|
||||
constructor (kubeConfigStr) {
|
||||
this.kubeConfigStr = kubeConfigStr
|
||||
this.init()
|
||||
}
|
||||
|
||||
init () {
|
||||
const kubeconfig = new KubeConfig()
|
||||
kubeconfig.loadFromString(this.kubeConfigStr)
|
||||
const reqOpts = { kubeconfig, request: {} }
|
||||
if (this.lookup) {
|
||||
reqOpts.request.lookup = this.lookup
|
||||
}
|
||||
|
||||
const backend = new Request(reqOpts)
|
||||
this.client = new Client({ backend, version: '1.13' })
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param localRecords { [domain]:{ip:'xxx.xx.xxx'} }
|
||||
*/
|
||||
setLookup (localRecords) {
|
||||
this.lookup = (hostnameReq, options, callback) => {
|
||||
logger.info('custom lookup', hostnameReq, localRecords)
|
||||
if (localRecords[hostnameReq]) {
|
||||
logger.info('local record', hostnameReq, localRecords[hostnameReq])
|
||||
callback(null, localRecords[hostnameReq].ip, 4)
|
||||
} else {
|
||||
dns.lookup(hostnameReq, options, callback)
|
||||
}
|
||||
}
|
||||
this.init()
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 secret列表
|
||||
* @param opts = {namespace:default}
|
||||
* @returns secretsList
|
||||
*/
|
||||
async getSecret (opts) {
|
||||
const namespace = opts.namespace || 'default'
|
||||
const secrets = await this.client.api.v1.namespaces(namespace).secrets.get()
|
||||
return secrets
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Secret
|
||||
* @param opts {namespace:default, body:yamlStr}
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
async createSecret (opts) {
|
||||
const namespace = opts.namespace || 'default'
|
||||
const created = await this.client.api.v1.namespaces(namespace).secrets.post({
|
||||
body: opts.body
|
||||
})
|
||||
logger.info('new secrets:', created)
|
||||
return created
|
||||
}
|
||||
|
||||
async updateSecret (opts) {
|
||||
const namespace = opts.namespace || 'default'
|
||||
const secretName = opts.secretName
|
||||
if (secretName == null) {
|
||||
throw new Error('secretName 不能为空')
|
||||
}
|
||||
return await this.client.api.v1.namespaces(namespace).secrets(secretName).put({
|
||||
body: opts.body
|
||||
})
|
||||
}
|
||||
|
||||
async patchSecret (opts) {
|
||||
const namespace = opts.namespace || 'default'
|
||||
const secretName = opts.secretName
|
||||
if (secretName == null) {
|
||||
throw new Error('secretName 不能为空')
|
||||
}
|
||||
return await this.client.api.v1.namespaces(namespace).secrets(secretName).patch({
|
||||
body: opts.body
|
||||
})
|
||||
}
|
||||
|
||||
async getIngress (opts) {
|
||||
const namespace = opts.namespace || 'default'
|
||||
const ingressName = opts.ingressName
|
||||
if (!ingressName) {
|
||||
throw new Error('ingressName 不能为空')
|
||||
}
|
||||
return await this.client.apis.extensions.v1beta1.namespaces(namespace).ingresses(ingressName).get()
|
||||
}
|
||||
|
||||
async patchIngress (opts) {
|
||||
const namespace = opts.namespace || 'default'
|
||||
const ingressName = opts.ingressName
|
||||
if (!ingressName) {
|
||||
throw new Error('ingressName 不能为空')
|
||||
}
|
||||
return await this.client.apis.extensions.v1beta1.namespaces(namespace).ingresses(ingressName).patch({
|
||||
body: opts.body
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import pkg from 'chai'
|
||||
import DnspodDnsProvider from '../../src/dns-providers/dnspod.js'
|
||||
import { createOptions } from '../../../../../test/options.js'
|
||||
const { expect } = pkg
|
||||
describe('DnspodDnsProvider', function () {
|
||||
it('#getDomainList', async function () {
|
||||
const options = createOptions()
|
||||
const dnsProvider = new DnspodDnsProvider(options.accessProviders.dnspod)
|
||||
const domainList = await dnsProvider.getDomainList()
|
||||
console.log('domainList', domainList)
|
||||
expect(domainList.length).gt(0)
|
||||
})
|
||||
|
||||
it('#createRecord&removeRecord', async function () {
|
||||
const options = createOptions()
|
||||
const dnsProvider = new DnspodDnsProvider(options.accessProviders.dnspod)
|
||||
const record = await dnsProvider.createRecord({ fullRecord: '___certd___.__test__.certd.xyz', type: 'TXT', value: 'aaaa' })
|
||||
console.log('recordId', record.id)
|
||||
expect(record.id != null).ok
|
||||
|
||||
await dnsProvider.removeRecord({ fullRecord: '___certd___.__test__.certd.xyz', type: 'TXT', value: 'aaaa', record })
|
||||
})
|
||||
})
|
||||
42
packages/plugins/plugin-tencent/test/options.js
Normal file
42
packages/plugins/plugin-tencent/test/options.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import _ from 'lodash-es'
|
||||
import optionsPrivate from '../../../../test/options.private.js'
|
||||
const defaultOptions = {
|
||||
version: '1.0.0',
|
||||
args: {
|
||||
directory: 'test',
|
||||
dry: false
|
||||
},
|
||||
accessProviders: {
|
||||
aliyun: {
|
||||
providerType: 'aliyun',
|
||||
accessKeyId: '',
|
||||
accessKeySecret: ''
|
||||
},
|
||||
myLinux: {
|
||||
providerType: 'SSH',
|
||||
username: 'xxx',
|
||||
password: 'xxx',
|
||||
host: '1111.com',
|
||||
port: 22,
|
||||
publicKey: ''
|
||||
}
|
||||
},
|
||||
cert: {
|
||||
domains: ['*.docmirror.club', 'docmirror.club'],
|
||||
email: 'xiaojunnuo@qq.com',
|
||||
dnsProvider: 'aliyun',
|
||||
certProvider: 'letsencrypt',
|
||||
csrInfo: {
|
||||
country: 'CN',
|
||||
state: 'GuangDong',
|
||||
locality: 'ShengZhen',
|
||||
organization: 'CertD Org.',
|
||||
organizationUnit: 'IT Department',
|
||||
emailAddress: 'xiaojunnuo@qq.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_.merge(defaultOptions, optionsPrivate)
|
||||
|
||||
export default defaultOptions
|
||||
@@ -0,0 +1,54 @@
|
||||
import pkg from 'chai'
|
||||
import { DeployCertToTencentCDN } from '../../src/plugins/deploy-to-cdn'
|
||||
import { Certd } from '@certd/certd'
|
||||
import { UploadCertToTencent } from '../../src/plugins/upload-to-tencent'
|
||||
import { createOptions } from '../../../../../test/options.js'
|
||||
const { expect } = pkg
|
||||
describe('DeployToTencentCDN', function () {
|
||||
it('#execute-from-store', async function () {
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
const certd = new Certd(options)
|
||||
const cert = certd.readCurrentCert('xiaojunnuo@qq.com', ['*.docmirror.cn'])
|
||||
const context = {}
|
||||
const uploadPlugin = new UploadCertToTencent()
|
||||
const uploadOptions = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: { name: 'certd部署测试', accessProvider: 'tencent' },
|
||||
context
|
||||
}
|
||||
await uploadPlugin.doExecute(uploadOptions)
|
||||
|
||||
const deployPlugin = new DeployCertToTencentCDN()
|
||||
const deployOpts = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: { domainName: 'tentcent-certd.docmirror.cn', certName: 'certd部署测试', accessProvider: 'tencent' },
|
||||
context
|
||||
}
|
||||
const ret = await deployPlugin.doExecute(deployOpts)
|
||||
expect(ret).ok
|
||||
console.log('context:', context)
|
||||
|
||||
await uploadPlugin.doRollback(uploadOptions)
|
||||
})
|
||||
it('#execute-upload', async function () {
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.docmirror.cn']
|
||||
const plugin = new DeployCertToTencentCDN()
|
||||
const certd = new Certd(options)
|
||||
const cert = await certd.readCurrentCert()
|
||||
const context = {}
|
||||
const deployOpts = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: { domainName: 'tentcent-certd.docmirror.cn', accessProvider: 'tencent' },
|
||||
context
|
||||
}
|
||||
const ret = await plugin.doExecute(deployOpts)
|
||||
console.log('context:', context, ret)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,107 @@
|
||||
import pkg from 'chai'
|
||||
import { DeployCertToTencentCLB } from '../../src/plugins/deploy-to-clb/index.js'
|
||||
import { Certd } from '@certd/certd'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { createOptions } from '../../../../../test/options.js'
|
||||
import { UploadCertToTencent } from '../../src/plugins/upload-to-tencent'
|
||||
const { expect } = pkg
|
||||
describe('DeployToTencentCLB', function () {
|
||||
it('#execute-getClbList', async function () {
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
options.cert.dnsProvider = 'tencent-yonsz'
|
||||
const deployPlugin = new DeployCertToTencentCLB()
|
||||
const props = {
|
||||
region: 'ap-guangzhou',
|
||||
domain: 'certd-test-no-sni.base.yonsz.net',
|
||||
accessProvider: 'tencent-yonsz'
|
||||
}
|
||||
const accessProviders = options.accessProviders
|
||||
const accessProvider = deployPlugin.getAccessProvider(props.accessProvider, accessProviders)
|
||||
const { region } = props
|
||||
const client = deployPlugin.getClient(accessProvider, region)
|
||||
|
||||
const ret = await deployPlugin.getCLBList(client, props)
|
||||
expect(ret.length > 0).ok
|
||||
console.log('clb count:', ret.length)
|
||||
})
|
||||
it('#execute-getListenerList', async function () {
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
options.cert.dnsProvider = 'tencent-yonsz'
|
||||
const deployPlugin = new DeployCertToTencentCLB(options)
|
||||
const props = {
|
||||
region: 'ap-guangzhou',
|
||||
domain: 'certd-test-no-sni.base.yonsz.net',
|
||||
accessProvider: 'tencent-yonsz',
|
||||
loadBalancerId: 'lb-59yhe5xo'
|
||||
}
|
||||
const accessProvider = deployPlugin.getAccessProvider(props.accessProvider)
|
||||
const { region } = props
|
||||
const client = deployPlugin.getClient(accessProvider, region)
|
||||
|
||||
const ret = await deployPlugin.getListenerList(client, props.loadBalancerId, props)
|
||||
expect(ret.length > 0).ok
|
||||
console.log('clb count:', ret.length, ret)
|
||||
})
|
||||
|
||||
it('#execute-no-sni-listenerId', async function () {
|
||||
this.timeout(10000)
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
options.cert.dnsProvider = 'tencent-yonsz'
|
||||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.docmirror.cn']
|
||||
const certd = new Certd(options)
|
||||
const cert = await certd.readCurrentCert()
|
||||
const deployPlugin = new DeployCertToTencentCLB()
|
||||
const context = {}
|
||||
const deployOpts = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: {
|
||||
region: 'ap-guangzhou',
|
||||
loadBalancerId: 'lb-59yhe5xo',
|
||||
listenerId: 'lbl-1vfwx8dq',
|
||||
accessProvider: 'tencent-yonsz'
|
||||
},
|
||||
context
|
||||
}
|
||||
const ret = await deployPlugin.doExecute(deployOpts)
|
||||
expect(ret).ok
|
||||
console.log('ret:', ret)
|
||||
|
||||
// 删除测试证书
|
||||
const uploadPlugin = new UploadCertToTencent()
|
||||
await uploadPlugin.doRollback(deployOpts)
|
||||
})
|
||||
|
||||
it('#execute-sni-listenerId', async function () {
|
||||
this.timeout(10000)
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
options.cert.dnsProvider = 'tencent-yonsz'
|
||||
const certd = new Certd(options)
|
||||
const cert = certd.readCurrentCert('xiaojunnuo@qq.com', ['*.docmirror.cn'])
|
||||
const deployPlugin = new DeployCertToTencentCLB()
|
||||
const context = {}
|
||||
const deployOpts = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: {
|
||||
region: 'ap-guangzhou',
|
||||
loadBalancerId: 'lb-59yhe5xo',
|
||||
listenerId: 'lbl-akbyf5ac',
|
||||
domain: 'certd-test-sni.base.yonsz.net',
|
||||
accessProvider: 'tencent-yonsz'
|
||||
},
|
||||
context
|
||||
}
|
||||
const ret = await deployPlugin.doExecute(deployOpts)
|
||||
expect(ret).ok
|
||||
console.log('ret:', ret)
|
||||
// 删除测试证书
|
||||
const uploadPlugin = new UploadCertToTencent()
|
||||
await uploadPlugin.doRollback(deployOpts)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,114 @@
|
||||
import pkg from 'chai'
|
||||
import { DeployCertToTencentTKEIngress } from '../../src/plugins/deploy-to-tke-ingress/index.js'
|
||||
import { Certd } from '@certd/certd'
|
||||
import { createOptions } from '../../../../../test/options.js'
|
||||
import { K8sClient } from '../../src/utils/util.k8s.client.js'
|
||||
|
||||
const { expect } = pkg
|
||||
|
||||
async function getOptions () {
|
||||
const options = createOptions()
|
||||
options.args.test = false
|
||||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.docmirror.cn']
|
||||
const certd = new Certd(options)
|
||||
const cert = await certd.readCurrentCert()
|
||||
const context = {}
|
||||
const deployOpts = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: {
|
||||
accessProvider: 'tencent-yonsz',
|
||||
region: 'ap-guangzhou',
|
||||
clusterId: 'cls-6lbj1vee'
|
||||
},
|
||||
context
|
||||
}
|
||||
return { options, deployOpts }
|
||||
}
|
||||
|
||||
describe('DeployCertToTencentTKEIngress', function () {
|
||||
// it('#getTkeKubeConfig', async function () {
|
||||
// const { options, deployOpts } = await getOptions()
|
||||
// const plugin = new DeployCertToTencentTKEIngress()
|
||||
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
|
||||
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
|
||||
// console.log('kubeConfig:', kubeConfig)
|
||||
// })
|
||||
//
|
||||
it('#getTKESecrets', async function () {
|
||||
this.timeout(50000)
|
||||
const { options, deployOpts } = await getOptions()
|
||||
const plugin = new DeployCertToTencentTKEIngress(options)
|
||||
const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
|
||||
const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props.clusterId)
|
||||
|
||||
const k8sClient = new K8sClient(kubeConfig)
|
||||
k8sClient.setLookup({
|
||||
'cls-6lbj1vee.ccs.tencent-cloud.com': { ip: '13.123.123.123' }
|
||||
})
|
||||
const secrets = await k8sClient.getSecret()
|
||||
|
||||
console.log('secrets:', secrets)
|
||||
})
|
||||
//
|
||||
// it('#patchTKECertSecrets', async function () {
|
||||
// this.timeout(5000)
|
||||
//
|
||||
// const { options, deployOpts } = await getOptions()
|
||||
// const plugin = new DeployCertToTencentTKEIngress()
|
||||
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
|
||||
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
|
||||
// const k8sClient = new K8sClient(kubeConfig)
|
||||
//
|
||||
// deployOpts.k8sClient = k8sClient
|
||||
// deployOpts.context.tencentCertId = 'hNVD3Z45'
|
||||
// const newCecret = await plugin.patchCertSecret(deployOpts)
|
||||
// console.log('newCecret', newCecret)
|
||||
// })
|
||||
// it('#GetTkeIngress', async function () {
|
||||
// this.timeout(5000)
|
||||
//
|
||||
// const { options, deployOpts } = await getOptions()
|
||||
// deployOpts.props.ingressName = 'ingress-base'
|
||||
// deployOpts.props.secretName = 'cert---docmirror-cn'
|
||||
// const plugin = new DeployCertToTencentTKEIngress()
|
||||
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
|
||||
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
|
||||
//
|
||||
// const k8sClient = new K8sClient(kubeConfig)
|
||||
// const ingress = await k8sClient.getIngress({
|
||||
// ingressName: 'ingress-base'
|
||||
// })
|
||||
// console.log('ingress:', ingress)
|
||||
// })
|
||||
// it('#RestartTKEIngress', async function () {
|
||||
// this.timeout(5000)
|
||||
//
|
||||
// const { options, deployOpts } = await getOptions()
|
||||
// deployOpts.props.ingressName = 'ingress-base'
|
||||
// deployOpts.props.secretName = 'cert---docmirror-cn'
|
||||
// const plugin = new DeployCertToTencentTKEIngress()
|
||||
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
|
||||
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
|
||||
//
|
||||
// const k8sClient = new K8sClient(kubeConfig)
|
||||
//
|
||||
// deployOpts.k8sClient = k8sClient
|
||||
// deployOpts.context.tencentCertId = 'hNVD3Z45'
|
||||
// const newCecret = await plugin.restartIngress(deployOpts)
|
||||
// console.log('newCecret', newCecret)
|
||||
// })
|
||||
|
||||
it('#execute', async function () {
|
||||
this.timeout(5000)
|
||||
const { deployOpts } = await getOptions()
|
||||
deployOpts.props.ingressName = 'ingress-base'
|
||||
deployOpts.props.secretName = 'cert---docmirror-cn'
|
||||
deployOpts.context.tencentCertId = 'hNUZJrZf'
|
||||
const plugin = new DeployCertToTencentTKEIngress()
|
||||
|
||||
const ret = await plugin.doExecute(deployOpts)
|
||||
console.log('sucess', ret)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
import pkg from 'chai'
|
||||
import { UploadCertToTencent } from '../../src/plugins/upload-to-tencent/index.js'
|
||||
import { Certd } from '@certd/certd'
|
||||
import { createOptions } from '../../../../../test/options.js'
|
||||
const { expect } = pkg
|
||||
describe('PluginUploadToTencent', function () {
|
||||
it('#execute', async function () {
|
||||
const options = createOptions()
|
||||
const plugin = new UploadCertToTencent()
|
||||
options.args = { test: false }
|
||||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.docmirror.cn']
|
||||
const certd = new Certd(options)
|
||||
const cert = await certd.readCurrentCert()
|
||||
const context = {}
|
||||
const uploadOpts = {
|
||||
accessProviders: options.accessProviders,
|
||||
cert,
|
||||
props: { name: 'certd部署测试', accessProvider: 'tencent' },
|
||||
context
|
||||
}
|
||||
await plugin.doExecute(uploadOpts)
|
||||
console.log('context:', context)
|
||||
|
||||
await plugin.doRollback(uploadOpts)
|
||||
})
|
||||
})
|
||||
1858
packages/plugins/plugin-tencent/yarn-error.log
Normal file
1858
packages/plugins/plugin-tencent/yarn-error.log
Normal file
File diff suppressed because it is too large
Load Diff
2922
packages/plugins/plugin-tencent/yarn.lock
Normal file
2922
packages/plugins/plugin-tencent/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user