chore: format

This commit is contained in:
xiaojunnuo
2026-05-31 01:41:33 +08:00
parent acd440106b
commit 4b57a0d729
557 changed files with 12530 additions and 14039 deletions
@@ -1,38 +1,36 @@
import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
import { VolcengineClient } from './ve-client.js';
import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
import { VolcengineClient } from "./ve-client.js";
/**
* 这个注解将注册一个授权配置
* 在certd的后台管理系统中,用户可以选择添加此类型的授权
*/
@IsAccess({
name: 'volcengine',
title: '火山引擎',
desc: '',
icon: 'svg:icon-volcengine',
name: "volcengine",
title: "火山引擎",
desc: "",
icon: "svg:icon-volcengine",
order: 1,
})
export class VolcengineAccess extends BaseAccess {
@AccessInput({
title: 'AccessKeyID',
title: "AccessKeyID",
component: {
placeholder: 'AccessKeyID',
placeholder: "AccessKeyID",
},
helper: "[获取密钥](https://console.volcengine.com/iam/keymanage/)",
required: true,
})
accessKeyId = '';
accessKeyId = "";
@AccessInput({
title: 'SecretAccessKey',
title: "SecretAccessKey",
component: {
placeholder: 'SecretAccessKey',
placeholder: "SecretAccessKey",
},
required: true,
encrypt: true,
})
secretAccessKey = '';
secretAccessKey = "";
@AccessInput({
title: "测试",
@@ -71,12 +69,9 @@ export class VolcengineAccess extends BaseAccess {
valid: true,
accountId: result.AccountId,
arn: result.Trn,
userId: result.IdentityId
userId: result.IdentityId,
};
}
}
new VolcengineAccess();
@@ -10,7 +10,6 @@ export class VolcengineCdnClient {
this.opts = opts;
}
async getCdnClient() {
if (this.service) {
return this.service;
@@ -34,15 +33,15 @@ export class VolcengineCdnClient {
PrivateKey: cert.key,
EncryType: "inter_cert",
Repeatable: false,
Desc: certName
Desc: certName,
});
if (res.ResponseMetadata?.Error) {
if (res.ResponseMetadata?.Error?.Code?.includes("Duplicated")) {
// 证书已存在,ID为 cert-16293a8524844a3e8e30ed62f8e5bc94。
const message = res.ResponseMetadata?.Error?.Message
const message = res.ResponseMetadata?.Error?.Message;
const reg = /ID为 (\S+)。/;
const certId = message.match(reg)?.[1]
const certId = message.match(reg)?.[1];
if (certId) {
this.opts.logger.info(`证书已存在,ID为 ${certId}`);
return certId;
@@ -51,10 +50,8 @@ export class VolcengineCdnClient {
throw new Error(JSON.stringify(res.ResponseMetadata?.Error));
}
const certId = res.Result.CertId
this.opts.logger.info(`上传证书成功:${certId}`)
const certId = res.Result.CertId;
this.opts.logger.info(`上传证书成功:${certId}`);
return certId;
}
}
@@ -1,18 +1,17 @@
import {http} from "@certd/basic";
import { http } from "@certd/basic";
import querystring from "querystring";
import {VolcengineOpts} from "./ve-client.js";
import { VolcengineOpts } from "./ve-client.js";
import { Pager, PageSearch } from "@certd/pipeline";
export type VolcengineReq = {
method?: string;
path?: string;
headers?: any;
body?: any;
query?: any;
service?: string, // 替换为实际服务名称
region?: string, // 替换为实际区域名称
}
service?: string; // 替换为实际服务名称
region?: string; // 替换为实际区域名称
};
export class VolcengineDnsClient {
opts: VolcengineOpts;
@@ -21,11 +20,10 @@ export class VolcengineDnsClient {
this.opts = opts;
}
async doRequest(req: VolcengineReq) {
const {Signer} =await import('@volcengine/openapi') ;
const { Signer } = await import("@volcengine/openapi");
// http request data
// http request data
const openApiRequestData: any = {
region: req.region,
method: req.method,
@@ -39,47 +37,42 @@ export class VolcengineDnsClient {
},
// [optional] http request body
body: req.body,
}
};
const signer = new Signer(openApiRequestData, req.service);
// sign
signer.addAuthorization({accessKeyId:this.opts.access.accessKeyId, secretKey:this.opts.access.secretAccessKey});
// sign
signer.addAuthorization({ accessKeyId: this.opts.access.accessKeyId, secretKey: this.opts.access.secretAccessKey });
// Print signed headers
// Print signed headers
console.log(openApiRequestData.headers);
const url = `https://open.volcengineapi.com/?${querystring.stringify(req.query)}`;
const url = `https://open.volcengineapi.com/?${querystring.stringify(req.query)}`
try{
try {
const res = await http.request({
url: url,
method: req.method,
headers: openApiRequestData.headers,
data:req.body
data: req.body,
});
if (res?.ResponseMetadata?.Error) {
const err = new Error(JSON.stringify(res.ResponseMetadata.Error));
// @ts-ignore
err.detail = res.ResponseMetadata.Error;
throw err
throw err;
}
return res
}catch (e) {
if(e.response){
return res;
} catch (e) {
if (e.response) {
const err = new Error(JSON.stringify(e.response.data.ResponseMetadata.Error));
// @ts-ignore
err.detail = e.response.data.ResponseMetadata.Error;
throw err
throw err;
}
}
}
async findDomain(domain: string) {
const req: VolcengineReq = {
method: "POST",
@@ -89,24 +82,24 @@ export class VolcengineDnsClient {
Action: "ListZones",
Version: "2018-08-01",
},
body:{
body: {
Key: domain,
SearchMode: "exact"
}
SearchMode: "exact",
},
};
return this.doRequest(req);
}
async getDomainList(page: PageSearch) {
const pager = new Pager(page)
const body:any = {
SearchMode: "like",
PageNumber: pager.pageNo,
PageSize: pager.pageSize,
}
async getDomainList(page: PageSearch) {
const pager = new Pager(page);
const body: any = {
SearchMode: "like",
PageNumber: pager.pageNo,
PageSize: pager.pageSize,
};
if (page.searchKey) {
body.Key = page.searchKey
body.Key = page.searchKey;
}
const req: VolcengineReq = {
method: "POST",
@@ -116,22 +109,21 @@ export class VolcengineDnsClient {
Action: "ListZones",
Version: "2018-08-01",
},
body:body
body: body,
};
const res = await this.doRequest(req);
let list = res.Result?.Zones || []
list = list.map((item:any) => {
let list = res.Result?.Zones || [];
list = list.map((item: any) => {
return {
id: item.ZID,
domain: item.ZoneName,
}
})
const total = res.Result?.Total|| list.length
};
});
const total = res.Result?.Total || list.length;
return {
list,
total
}
total,
};
}
}
@@ -1,6 +1,6 @@
export * from './plugins/index.js';
export * from './access.js';
export * from './volcengine-dns-provider.js';
export * from './ve-client.js';
export * from './dns-client.js';
export * from './cdn-client.js';
export * from "./plugins/index.js";
export * from "./access.js";
export * from "./volcengine-dns-provider.js";
export * from "./ve-client.js";
export * from "./dns-client.js";
export * from "./cdn-client.js";
@@ -1,9 +1,9 @@
export * from './plugin-deploy-to-cdn.js'
export * from './plugin-deploy-to-clb.js'
export * from './plugin-upload-to-cert-center.js'
export * from './plugin-deploy-to-alb.js'
export * from './plugin-deploy-to-live.js'
export * from './plugin-deploy-to-dcdn.js'
export * from './plugin-deploy-to-vod.js'
export * from './plugin-deploy-to-tos.js'
export * from './plugin-deploy-to-vke.js'
export * from "./plugin-deploy-to-cdn.js";
export * from "./plugin-deploy-to-clb.js";
export * from "./plugin-upload-to-cert-center.js";
export * from "./plugin-deploy-to-alb.js";
export * from "./plugin-deploy-to-live.js";
export * from "./plugin-deploy-to-dcdn.js";
export * from "./plugin-deploy-to-vod.js";
export * from "./plugin-deploy-to-tos.js";
export * from "./plugin-deploy-to-vke.js";
@@ -13,9 +13,9 @@ import dayjs from "dayjs";
desc: "部署至火山引擎应用负载均衡",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToALB extends AbstractTaskPlugin {
@TaskInput({
@@ -23,25 +23,23 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"]
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"],
},
required: true
required: true,
})
cert!: CertInfo | string;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine"
type: "volcengine",
},
required: true
required: true,
})
accessId!: string;
@@ -106,28 +104,25 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
{ label: "广州", value: "cn-guangzhou" },
{ label: "香港", value: "cn-hongkong" },
{ label: "柔佛", value: "ap-southeast-1" },
{ label: "雅加达", value: "ap-southeast-3" }
]
{ label: "雅加达", value: "ap-southeast-3" },
],
},
value: "cn-beijing",
required: true
required: true,
})
regionId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "监听器列表",
helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心,进行跨服务访问授权",
action: VolcengineDeployToALB.prototype.onGetListenerList.name,
watches: ["certDomains", "accessId", "regionId"],
required: true
required: true,
})
)
listenerList!: string | string[];
@TaskInput({
title: "证书部署类型",
helper: "选择部署默认证书还是扩展证书",
@@ -135,17 +130,15 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
name: "a-select",
options: [
{ label: "默认证书", value: "default" },
{ label: "扩展证书", value: "extension" }
]
{ label: "扩展证书", value: "extension" },
],
},
value: "default",
required: true
required: true,
})
certType!: string;
async onInstance() {
}
async onInstance() {}
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎ALB");
@@ -156,8 +149,8 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
const certInfo = this.cert as CertInfo;
this.logger.info(`开始上传证书`);
certId = await certService.ImportCertificate({
certName:this.appendTimeSuffix("certd"),
cert:certInfo
certName: this.appendTimeSuffix("certd"),
cert: certInfo,
});
this.logger.info(`上传证书成功:${certId}`);
} else {
@@ -174,8 +167,8 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
query: {
ListenerId: listener,
CertificateSource: "cert_center",
CertCenterCertificateId: certId
}
CertCenterCertificateId: certId,
},
});
this.logger.info(`部署监听器${listener}默认证书成功,res:${JSON.stringify(res)}`);
} else {
@@ -191,12 +184,12 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
private async deployExtensionCertificate(service: any, listenerId: string, certId: string) {
// 获取监听器当前的扩展证书列表
const domainExtensions = await this.getListenerDomainExtensions(service, listenerId);
// 删除过期的扩展证书
try {
await this.deleteExpiredExtensions(service, listenerId, domainExtensions);
} catch (error) {
this.logger.error(`删除过期扩展证书失败:${error.message ||error}`);
this.logger.error(`删除过期扩展证书失败:${error.message || error}`);
}
// 新增扩展证书
@@ -204,7 +197,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
ListenerId: listenerId,
"DomainExtensions.1.Action": "create",
"DomainExtensions.1.CertificateSource": "cert_center",
"DomainExtensions.1.CertCenterCertificateId": certId
"DomainExtensions.1.CertCenterCertificateId": certId,
};
// 如果有证书域名信息,添加到扩展证书中
@@ -214,7 +207,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
await service.request({
action: "ModifyListenerAttributes",
query: query
query: query,
});
this.logger.info(`部署监听器${listenerId}扩展证书成功`);
}
@@ -224,17 +217,17 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
action: "DescribeListenerAttributes",
method: "GET",
query: {
ListenerId: listenerId
}
ListenerId: listenerId,
},
});
return res.Result.DomainExtensions || [];
}
private async deleteExpiredExtensions(service: any, listenerId: string, domainExtensions: any[]) {
const expiredExtensions = [];
for (const ext of domainExtensions) {
if (!await this.isCertificateExpired(ext)) {
if (!(await this.isCertificateExpired(ext))) {
expiredExtensions.push(ext);
}
}
@@ -244,30 +237,29 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
}
const query: any = {
ListenerId: listenerId
ListenerId: listenerId,
};
expiredExtensions.forEach((ext, index) => {
const idx = index + 1;
query[`DomainExtensions.${idx}.Action`] = "delete";
query[`DomainExtensions.${idx}.DomainExtensionId`] = ext.DomainExtensionId;
});
this.logger.info(`准备删除过期扩展证书,数量:${expiredExtensions.length}个,query:${JSON.stringify(query)}`);
await service.request({
action: "ModifyListenerAttributes",
query: query
query: query,
});
this.logger.info(`删除${expiredExtensions.length}个过期扩展证书成功`);
await this.ctx.utils.sleep(5000);
await this.ctx.utils.sleep(5000);
}
private async getCertService(access: VolcengineAccess) {
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
return await client.getCertCenterService();
@@ -279,11 +271,11 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
const service = await client.getAlbService({
region: this.regionId
region: this.regionId,
});
return service;
}
@@ -291,7 +283,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
private async isCertificateExpired(extension: any): Promise<boolean> {
try {
let certificateId: string;
// 根据证书来源获取证书ID
if (extension.CertificateSource === "cert_center") {
certificateId = extension.CertCenterCertificateId;
@@ -305,19 +297,19 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
this.logger.warn(`未知的证书来源: ${extension.CertificateSource},跳过`);
return false;
}
if (!certificateId) {
this.logger.warn(`证书ID为空,跳过`);
return false;
}
// 获取证书服务
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const certService = await this.getCertService(access);
// 获取证书详情
const certDetail = await certService.GetCertificateDetail(certificateId);
// 判断证书是否过期
if (certDetail.NotAfter) {
const expireTime = dayjs(certDetail.NotAfter);
@@ -328,7 +320,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
}
return isExpired;
}
return false;
} catch (error) {
this.logger.error(`检查证书是否过期失败: ${error.message || error}`);
@@ -347,7 +339,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
method: "GET",
query: {
PageSize: 100,
Protocol: "HTTPS"
Protocol: "HTTPS",
},
});
@@ -358,7 +350,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin {
return list.map((item: any) => {
return {
value: item.ListenerId,
label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>`
label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>`,
};
});
}
@@ -6,11 +6,11 @@ import { VolcengineAccess } from "../access.js";
import { VolcengineCdnClient } from "../cdn-client.js";
@IsTaskPlugin({
name: 'VolcengineDeployToCDN',
title: '火山引擎-部署证书至CDN',
icon: 'svg:icon-volcengine',
name: "VolcengineDeployToCDN",
title: "火山引擎-部署证书至CDN",
icon: "svg:icon-volcengine",
group: pluginGroups.volcengine.key,
desc: '支持网页,文件下载,音视频点播',
desc: "支持网页,文件下载,音视频点播",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
@@ -19,11 +19,11 @@ import { VolcengineCdnClient } from "../cdn-client.js";
})
export class VolcengineDeployToCDN extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: 'output-selector',
from: [...CertApplyPluginNames, 'VolcengineUploadToCertCenter'],
name: "output-selector",
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"],
},
required: true,
})
@@ -32,111 +32,105 @@ export class VolcengineDeployToCDN extends AbstractTaskPlugin {
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'Access授权',
helper: '火山引擎AccessKeyId、AccessKeySecret',
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: 'access-selector',
type: 'volcengine',
name: "access-selector",
type: "volcengine",
},
required: true,
})
accessId!: string;
@TaskInput({
title: '服务类型',
helper: '网页,文件下载,音视频点播',
title: "服务类型",
helper: "网页,文件下载,音视频点播",
component: {
name: 'a-select',
options:[
name: "a-select",
options: [
{ label: "网页", value: "web" },
{ label: "文件下载", value: "download" },
{ label: "音视频点播", value: 'video'},
]
{ label: "音视频点播", value: "video" },
],
},
value: 'web',
value: "web",
required: true,
})
serviceType:string = "web"
serviceType = "web";
@TaskInput(
createRemoteSelectInputDefine({
title: 'CDN加速域名',
helper: '你在火山引擎上配置的CDN加速域名,比如:certd.docmirror.cn',
title: "CDN加速域名",
helper: "你在火山引擎上配置的CDN加速域名,比如:certd.docmirror.cn",
action: VolcengineDeployToCDN.prototype.onGetDomainList.name,
watches: ['certDomains', 'accessId', 'serviceType'],
watches: ["certDomains", "accessId", "serviceType"],
required: true,
})
)
domainName!: string | string[];
async onInstance() {}
async execute(): Promise<void> {
this.logger.info('开始部署证书到火山引擎CDN');
this.logger.info("开始部署证书到火山引擎CDN");
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = await this.getClient(access)
const service = await client.getCdnClient()
const client = await this.getClient(access);
const service = await client.getCdnClient();
if (!this.cert) {
throw new Error('你还未选择证书');
throw new Error("你还未选择证书");
}
let certId = this.cert
if (typeof certId !== 'string') {
const certInfo = this.cert as CertInfo
this.logger.info(`开始上传证书`)
certId = await client.uploadCert(certInfo, this.appendTimeSuffix('certd'))
let certId = this.cert;
if (typeof certId !== "string") {
const certInfo = this.cert as CertInfo;
this.logger.info(`开始上传证书`);
certId = await client.uploadCert(certInfo, this.appendTimeSuffix("certd"));
this.logger.info(`上传证书成功:${certId}`);
}else{
} else {
this.logger.info(`使用已有证书ID${certId}`);
}
for (const domain of this.domainName) {
this.logger.info(`开始部署域名${domain}证书`)
this.logger.info(`开始部署域名${domain}证书`);
await service.UpdateCdnConfig({
Domain: domain,
HTTPS: {
CertInfo: { CertId: certId as string },
Switch: true,
}
})
},
});
this.logger.info(`部署域名${domain}证书成功`);
await this.ctx.utils.sleep(1000)
await this.ctx.utils.sleep(1000);
}
this.logger.info('部署完成');
this.logger.info("部署完成");
}
async getClient(access: VolcengineAccess) {
return new VolcengineCdnClient({
return new VolcengineCdnClient({
logger: this.logger,
access,
http:this.http
})
http: this.http,
});
}
async onGetDomainList(data: any) {
if (!this.accessId) {
throw new Error('请选择Access授权');
throw new Error("请选择Access授权");
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = await this.getClient(access);
const service = await client.getCdnClient()
const service = await client.getCdnClient();
const res = await service.ListCdnDomains({
ServiceType: this.serviceType,
PageNum: 1,
PageSize: 100,
})
});
// @ts-ignore
const list = res?.Result?.Data
const list = res?.Result?.Data;
if (!list || list.length === 0) {
throw new Error('找不到加速域名,您可以手动输入');
throw new Error("找不到加速域名,您可以手动输入");
}
const options = list.map((item: any) => {
return {
@@ -12,9 +12,9 @@ import { VolcengineClient } from "../ve-client.js";
desc: "部署至火山引擎负载均衡",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToCLB extends AbstractTaskPlugin {
@TaskInput({
@@ -22,24 +22,23 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"]
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"],
},
required: true
required: true,
})
cert!: CertInfo | string;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine"
type: "volcengine",
},
required: true
required: true,
})
accessId!: string;
@@ -109,30 +108,26 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
{ label: "重庆", value: "cn-chengdu" },
{ label: "香港", value: "cn-hongkong" },
{ label: "柔佛", value: "ap-southeast-1" },
{ label: "雅加达", value: "ap-southeast-3" }
]
{ label: "雅加达", value: "ap-southeast-3" },
],
},
value: "cn-beijing",
required: true
required: true,
})
regionId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "监听器列表",
helper: "选择要部署证书的监听器\n<span class='color-blue'>需要在监听器中选择证书中心,进行跨服务访问授权</span>",
action: VolcengineDeployToCLB.prototype.onGetListenerList.name,
watches: ["certDomains", "accessId", "regionId"],
required: true
required: true,
})
)
listenerList!: string | string[];
async onInstance() {
}
async onInstance() {}
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎CLB");
@@ -143,8 +138,8 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
const certInfo = this.cert as CertInfo;
this.logger.info(`开始上传证书`);
certId = await certService.ImportCertificate({
certName:this.appendTimeSuffix("certd"),
cert:certInfo
certName: this.appendTimeSuffix("certd"),
cert: certInfo,
});
this.logger.info(`上传证书成功:${certId}`);
} else {
@@ -159,8 +154,8 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
query: {
ListenerId: listener,
CertificateSource: "cert_center",
CertCenterCertificateId: certId
}
CertCenterCertificateId: certId,
},
});
this.logger.info(`部署监听器${listener}证书成功`);
}
@@ -168,12 +163,11 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
this.logger.info("部署完成");
}
private async getCertService(access: VolcengineAccess) {
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
return await client.getCertCenterService();
@@ -188,7 +182,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
action: "DescribeLoadBalancers",
method: "GET",
query: {
PageSize: 100
PageSize: 100,
},
});
@@ -197,7 +191,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
return list.map((item: any) => {
return {
value: item.LoadBalancerId,
label: `${item.LoadBalancerName}<${item.Description}>`
label: `${item.LoadBalancerName}<${item.Description}>`,
};
});
}
@@ -208,11 +202,11 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
const service = await client.getClbService({
region: this.regionId
region: this.regionId,
});
return service;
}
@@ -228,7 +222,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
method: "GET",
query: {
PageSize: 100,
Protocol: "HTTPS"
Protocol: "HTTPS",
},
});
@@ -239,7 +233,7 @@ export class VolcengineDeployToCLB extends AbstractTaskPlugin {
return list.map((item: any) => {
return {
value: item.ListenerId,
label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>`
label: `${item.ListenerName}<${item.Description}:${item.ListenerId}>`,
};
});
}
@@ -1,204 +1,196 @@
import {AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from "@certd/pipeline";
import {createCertDomainGetterInputDefine, createRemoteSelectInputDefine} from "@certd/plugin-lib";
import {CertApplyPluginNames, CertInfo, CertReader} from "@certd/plugin-cert";
import {VolcengineAccess} from "../access.js";
import {VolcengineClient} from "../ve-client.js";
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert";
import { VolcengineAccess } from "../access.js";
import { VolcengineClient } from "../ve-client.js";
@IsTaskPlugin({
name: "VolcengineDeployToDCDN",
title: "火山引擎-部署证书至DCDN",
icon: "svg:icon-volcengine",
group: pluginGroups.volcengine.key,
desc: "部署至火山引擎全站加速",
// showRunStrategy: true,
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
name: "VolcengineDeployToDCDN",
title: "火山引擎-部署证书至DCDN",
icon: "svg:icon-volcengine",
group: pluginGroups.volcengine.key,
desc: "部署至火山引擎全站加速",
// showRunStrategy: true,
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToDCDN extends AbstractTaskPlugin {
@TaskInput({
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames]
},
required: true
})
cert!: CertInfo;
@TaskInput({
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames],
},
required: true,
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine({props: {required: false}}))
certDomains!: string[];
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "自动匹配",
helper: "是否根据证书自动匹配合适的DCDN域名进行部署",
value: false,
component: {
name: "a-switch",
type: "checked"
},
required: true
})
autoMatch!: boolean;
@TaskInput({
title: "自动匹配",
helper: "是否根据证书自动匹配合适的DCDN域名进行部署",
value: false,
component: {
name: "a-switch",
type: "checked",
},
required: true,
})
autoMatch!: boolean;
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine"
},
required: true
})
accessId!: string;
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine",
},
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "DCDN域名",
helper: "选择要部署证书的DCDN域名",
action: VolcengineDeployToDCDN.prototype.onGetDomainList.name,
watches: ["certDomains", "accessId"],
required: true,
mergeScript: `
@TaskInput(
createRemoteSelectInputDefine({
title: "DCDN域名",
helper: "选择要部署证书的DCDN域名",
action: VolcengineDeployToDCDN.prototype.onGetDomainList.name,
watches: ["certDomains", "accessId"],
required: true,
mergeScript: `
return {
show: ctx.compute(({form})=>{
return !form.autoMatch
})
}
`
})
)
domainList!: string | string[];
`,
})
)
domainList!: string | string[];
async onInstance() {}
async onInstance() {
async uploadCert(client: VolcengineClient) {
const certService = await client.getCertCenterService();
let certId = this.cert;
if (typeof certId !== "string") {
const certInfo = this.cert as CertInfo;
this.logger.info(`开始上传证书`);
certId = await certService.ImportCertificate({
certName: this.appendTimeSuffix("certd"),
cert: certInfo,
});
this.logger.info(`上传证书成功:${certId}`);
} else {
this.logger.info(`使用已有证书ID:${certId}`);
}
return certId;
}
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎DCDN");
const client = await this.getClient();
const certId = await this.uploadCert(client);
const service = await client.getDCDNService();
this.certDomains = new CertReader(this.cert).getAllDomains();
let domainList = this.domainList;
if (!this.autoMatch) {
//手动根据域名部署
if (!this.domainList || this.domainList.length === 0) {
throw new Error("域名列表不能为空");
}
} else {
//自动匹配
const options = await this.getDomainOptions(service);
const grouped = this.ctx.utils.options.groupByDomain(options, this.certDomains);
const matched = grouped.matched;
domainList = matched.map(item => item.domain);
if (domainList.length === 0) {
this.logger.warn("没有匹配到域名,跳过部署");
this.logger.info("当前证书域名:", this.certDomains);
this.logger.info(
"当前DCDN域名:",
grouped.notMatched.map(item => item.domain)
);
return;
}
}
async uploadCert(client: VolcengineClient) {
const certService = await client.getCertCenterService();
let certId = this.cert;
if (typeof certId !== "string") {
const certInfo = this.cert as CertInfo;
this.logger.info(`开始上传证书`);
certId = await certService.ImportCertificate({
certName: this.appendTimeSuffix("certd"),
cert: certInfo
});
this.logger.info(`上传证书成功:${certId}`);
} else {
this.logger.info(`使用已有证书ID:${certId}`);
}
return certId
//域名十个十个的分割
for (let i = 0; i < domainList.length; i += 10) {
const batch = domainList.slice(i, i + 10);
this.logger.info(`开始部署证书到域名:${batch}`);
const res = await service.request({
action: "CreateCertBind",
method: "POST",
body: {
DomainNames: batch,
CertSource: "volc",
CertId: certId,
},
version: "2021-04-01",
});
this.logger.info(`部署证书到域名成功:`, JSON.stringify(res));
}
this.logger.info("部署完成");
}
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎DCDN");
async getClient() {
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = await this.getClient();
let certId = await this.uploadCert(client);
const service = await client.getDCDNService();
this.certDomains = new CertReader(this.cert).getAllDomains()
let domainList = this.domainList
if (!this.autoMatch) {
//手动根据域名部署
if (!this.domainList || this.domainList.length === 0) {
throw new Error("域名列表不能为空");
}
} else {
//自动匹配
const options = await this.getDomainOptions(service);
const grouped = this.ctx.utils.options.groupByDomain(options, this.certDomains);
const matched = grouped.matched
domainList = matched.map(item => item.domain)
if (domainList.length === 0) {
this.logger.warn("没有匹配到域名,跳过部署")
this.logger.info("当前证书域名:", this.certDomains)
this.logger.info("当前DCDN域名:", grouped.notMatched.map(item => item.domain))
return
}
}
//域名十个十个的分割
for (let i = 0; i < domainList.length; i += 10) {
const batch = domainList.slice(i, i + 10);
this.logger.info(`开始部署证书到域名:${batch}`);
const res = await service.request({
action: "CreateCertBind",
method: "POST",
body: {
"DomainNames": batch,
"CertSource": "volc",
"CertId": certId
},
version: "2021-04-01"
});
this.logger.info(`部署证书到域名成功:`,JSON.stringify(res));
}
this.logger.info("部署完成");
return new VolcengineClient({
logger: this.logger,
access,
http: this.http,
});
}
async onGetDomainList(data: any) {
if (!this.accessId) {
throw new Error("请选择Access授权");
}
const client = await this.getClient();
const service = await client.getDCDNService();
const options = await this.getDomainOptions(service);
return this.ctx.utils.options.buildGroupOptions(options, this.certDomains);
}
async getClient() {
const access = await this.getAccess<VolcengineAccess>(this.accessId);
private async getDomainOptions(service: any) {
const res = await service.request({
method: "POST",
action: "DescribeUserDomains",
body: {
PageSize: 1000,
},
});
return new VolcengineClient({
logger: this.logger,
access,
http: this.http
})
const list = res.Result?.Domains;
if (!list || list.length === 0) {
throw new Error("找不到DCDN域名,您也可以手动输入域名");
}
async onGetDomainList(data: any) {
if (!this.accessId) {
throw new Error("请选择Access授权");
}
const client = await this.getClient();
const service = await client.getDCDNService();
const options = await this.getDomainOptions(service);
return this.ctx.utils.options.buildGroupOptions(options, this.certDomains);
}
private async getDomainOptions(service: any) {
const res = await service.request({
method: "POST",
action: "DescribeUserDomains",
body: {
"PageSize": 1000
}
})
const list = res.Result?.Domains;
if (!list || list.length === 0) {
throw new Error("找不到DCDN域名,您也可以手动输入域名");
}
const options = list.map((item: any) => {
return {
value: item.Domain,
label: `${item.Domain}<${item.Scope}>`,
domain: item.Domain
};
});
return options;
}
const options = list.map((item: any) => {
return {
value: item.Domain,
label: `${item.Domain}<${item.Scope}>`,
domain: item.Domain,
};
});
return options;
}
}
new VolcengineDeployToDCDN();
@@ -12,9 +12,9 @@ import { VolcengineClient } from "../ve-client.js";
desc: "部署至火山引擎视频直播",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToLive extends AbstractTaskPlugin {
@TaskInput({
@@ -22,48 +22,43 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin {
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames]
from: [...CertApplyPluginNames],
},
required: true
required: true,
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine"
type: "volcengine",
},
required: true
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "直播域名",
helper: "选择要部署证书的直播域名",
action: VolcengineDeployToLive.prototype.onGetDomainList.name,
watches: ["certDomains", "accessId"],
required: true
required: true,
})
)
domainList!: string | string[];
async onInstance() {
}
async onInstance() {}
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎视频直播");
const service = await this.getLiveService();
let certId = await this.uploadCert(service);
const certId = await this.uploadCert(service);
for (const item of this.domainList) {
this.logger.info(`开始部署直播域名${item}证书`);
@@ -72,8 +67,8 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin {
body: {
Domain: item,
HTTPS: true,
ChainID: certId
}
ChainID: certId,
},
});
this.logger.info(`部署直播域名${item}证书成功`);
}
@@ -81,17 +76,16 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin {
this.logger.info("部署完成");
}
private async uploadCert(liveService: any) {
const res = await liveService.request({
action: "CreateCert",
body: {
Rsa: {
Pubkey: this.cert.crt,
Prikey: this.cert.key
Prikey: this.cert.key,
},
UseWay: "https"
}
UseWay: "https",
},
});
const certId = res.Result.ChainID;
@@ -99,14 +93,13 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin {
return certId;
}
private async getLiveService() {
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
return await client.getLiveService();
@@ -121,9 +114,9 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin {
const res = await service.request({
action: "ListDomainDetail",
body: {
"PageNum": 1,
"PageSize": 100
}
PageNum: 1,
PageSize: 100,
},
});
const list = res.Result?.DomainList;
@@ -134,7 +127,7 @@ export class VolcengineDeployToLive extends AbstractTaskPlugin {
return {
value: item.Domain,
label: `${item.Domain}<${item.Type}>`,
domain: item.Domain
domain: item.Domain,
};
});
return this.ctx.utils.options.buildGroupOptions(options, this.certDomains);
@@ -6,11 +6,11 @@ import { VolcengineAccess } from "../access.js";
import { VolcengineClient } from "../ve-client.js";
@IsTaskPlugin({
name: 'VolcengineDeployToTOS',
title: '火山引擎-部署证书至TOS自定义域名',
icon: 'svg:icon-volcengine',
name: "VolcengineDeployToTOS",
title: "火山引擎-部署证书至TOS自定义域名",
icon: "svg:icon-volcengine",
group: pluginGroups.volcengine.key,
desc: '仅限TOS自定义域名,加速域名请选择火山引擎的CDN插件',
desc: "仅限TOS自定义域名,加速域名请选择火山引擎的CDN插件",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
@@ -19,11 +19,11 @@ import { VolcengineClient } from "../ve-client.js";
})
export class VolcengineDeployToTOS extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: 'output-selector',
from: [...CertApplyPluginNames, 'VolcengineUploadToCertCenter'],
name: "output-selector",
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"],
},
required: true,
})
@@ -32,48 +32,47 @@ export class VolcengineDeployToTOS extends AbstractTaskPlugin {
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'Access授权',
helper: '火山引擎AccessKeyId、AccessKeySecret',
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: 'access-selector',
type: 'volcengine',
name: "access-selector",
type: "volcengine",
},
required: true,
})
accessId!: string;
@TaskInput({
title: '地域',
helper: 'TOS服务所在地域',
title: "地域",
helper: "TOS服务所在地域",
component: {
name: 'a-select',
options:[
name: "a-select",
options: [
{ label: "华北2(北京)", value: "cn-beijing" },
{ label: "华东2(上海)", value: "cn-shanghai" },
{ label: "华南1(广州)", value: "cn-guangzhou" },
{ label: "中国香港", value: "cn-hongkong" },
{ label: "亚太东南(柔佛)", value: "ap-southeast-1" },
{ label: "亚太东南(雅加达)", value: "ap-southeast-3" },
]
],
},
value: 'cn-beijing',
value: "cn-beijing",
required: true,
})
region:string = "cn-beijing"
region = "cn-beijing";
@TaskInput({
title: 'Bucket',
helper: '存储桶名称',
title: "Bucket",
helper: "存储桶名称",
component: {
name: 'remote-auto-complete',
vModel: 'value',
type: 'plugin',
action: 'onGetBucketList',
name: "remote-auto-complete",
vModel: "value",
type: "plugin",
action: "onGetBucketList",
search: false,
pager: false,
watches: ['accessId', 'region']
watches: ["accessId", "region"],
},
required: true,
})
@@ -81,87 +80,86 @@ export class VolcengineDeployToTOS extends AbstractTaskPlugin {
@TaskInput(
createRemoteSelectInputDefine({
title: 'TOS自定义域名',
helper: '你在火山引擎上配置的TOS自定义域名,比如:example.com',
title: "TOS自定义域名",
helper: "你在火山引擎上配置的TOS自定义域名,比如:example.com",
action: VolcengineDeployToTOS.prototype.onGetDomainList.name,
watches: ['certDomains', 'accessId', 'region', 'bucket'],
watches: ["certDomains", "accessId", "region", "bucket"],
required: true,
})
)
domainName!: string | string[];
async onInstance() {}
async execute(): Promise<void> {
this.logger.info('开始部署证书到火山引擎TOS自定义域名');
this.logger.info("开始部署证书到火山引擎TOS自定义域名");
const access = await this.getAccess<VolcengineAccess>(this.accessId);
this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
const tosService = await client.getTOSService({ region: this.region });
if (!this.cert) {
throw new Error('你还未选择证书');
throw new Error("你还未选择证书");
}
let certId = this.cert
if (typeof certId !== 'string') {
const certInfo = this.cert as CertInfo
this.logger.info(`开始上传证书`)
let certId = this.cert;
if (typeof certId !== "string") {
const certInfo = this.cert as CertInfo;
this.logger.info(`开始上传证书`);
const certService = await client.getCertCenterService();
certId = await certService.ImportCertificate({
certName: this.appendTimeSuffix('certd'),
cert: certInfo
})
certName: this.appendTimeSuffix("certd"),
cert: certInfo,
});
this.logger.info(`上传证书成功:${certId}`);
}else{
} else {
this.logger.info(`使用已有证书ID${certId}`);
}
for (const domain of this.domainName) {
this.logger.info(`开始部署域名${domain}证书`)
this.logger.info(`开始部署域名${domain}证书`);
await tosService.putBucketCustomDomain({
bucket: this.bucket,
customDomainRule: {
Domain: domain,
CertId: certId as string
}
})
CertId: certId as string,
},
});
this.logger.info(`部署域名${domain}证书成功`);
await this.ctx.utils.sleep(1000)
await this.ctx.utils.sleep(1000);
}
this.logger.info('部署完成');
this.logger.info("部署完成");
}
async onGetDomainList(data: any) {
if (!this.accessId || !this.bucket) {
throw new Error('请选择Access授权和Bucket');
throw new Error("请选择Access授权和Bucket");
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
const tosService = await client.getTOSService({ region: this.region });
const res = await tosService.getBucketCustomDomain({
bucket: this.bucket
bucket: this.bucket,
});
const list = res?.data?.CustomDomainRules || [];
if (!list || list.length === 0) {
throw new Error('找不到TOS自定义域名,您可以手动输入');
throw new Error("找不到TOS自定义域名,您可以手动输入");
}
const options = list.map((item: any) => {
return {
value: item.Domain,
@@ -169,31 +167,31 @@ export class VolcengineDeployToTOS extends AbstractTaskPlugin {
domain: item.Domain,
};
});
return optionsUtils.buildGroupOptions(options, this.certDomains);
}
async onGetBucketList(data: any) {
if (!this.accessId) {
throw new Error('请选择Access授权');
throw new Error("请选择Access授权");
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
const tosService = await client.getTOSService({ region: this.region });
const res = await tosService.listBuckets();
const buckets = res?.data?.Buckets || [];
return buckets.map((bucket: any) => ({
label: `${bucket.Name}<${bucket.Location}>`,
value: bucket.Name
value: bucket.Name,
}));
}
}
new VolcengineDeployToTOS();
new VolcengineDeployToTOS();
@@ -23,7 +23,7 @@ describe("VolcengineDeployToVKE", () => {
request: async (req: any) => {
requestBody = req.body;
return { Result: { Id: "kc-123" } };
}
},
});
assert.equal(kubeconfigId, "kc-123");
@@ -35,23 +35,15 @@ describe("VolcengineDeployToVKE", () => {
plugin.clusterId = "cc1234567890123456789";
plugin.kubeconfigType = "Public";
const kubeconfig = [
"apiVersion: v1",
"clusters:",
"- cluster:",
" server: https://example.com",
" name: vke",
"contexts: []",
"current-context: vke"
].join("\n");
const kubeconfig = ["apiVersion: v1", "clusters:", "- cluster:", " server: https://example.com", " name: vke", "contexts: []", "current-context: vke"].join("\n");
const result = await (plugin as any).getKubeconfig(
{
request: async () => ({
Result: {
Items: [{ Id: "kc-123", Kubeconfig: Buffer.from(kubeconfig).toString("base64") }]
}
})
Items: [{ Id: "kc-123", Kubeconfig: Buffer.from(kubeconfig).toString("base64") }],
},
}),
},
"kc-123"
);
@@ -66,11 +58,10 @@ describe("VolcengineDeployToVKE", () => {
const message = (plugin as any).formatK8sError({
status: "Failure",
message:
'secrets "aaaa" is forbidden: User "2100656669-kd7ubde6lsvqbdgsa40t0" cannot get resource "secrets" in API group "" in the namespace "default"',
message: 'secrets "aaaa" is forbidden: User "2100656669-kd7ubde6lsvqbdgsa40t0" cannot get resource "secrets" in API group "" in the namespace "default"',
reason: "Forbidden",
details: { name: "aaaa", kind: "secrets" },
code: 403
code: 403,
});
assert.match(message, /VKE集群RBAC权限不足/);
@@ -89,8 +80,8 @@ describe("VolcengineDeployToVKE", () => {
() =>
(plugin as any).getTargetSecretNames({
getIngressList: async () => ({
items: [{ metadata: { name: "app-web" } }, { metadata: { name: "api-web" } }]
})
items: [{ metadata: { name: "app-web" } }, { metadata: { name: "api-web" } }],
}),
}),
/当前命名空间可用Ingress:app-web,api-web/
);
@@ -11,7 +11,7 @@ const regionOptions = [
{ label: "广州", value: "cn-guangzhou" },
{ label: "香港", value: "cn-hongkong" },
{ label: "柔佛", value: "ap-southeast-1" },
{ label: "雅加达", value: "ap-southeast-3" }
{ label: "雅加达", value: "ap-southeast-3" },
];
@IsTaskPlugin({
@@ -22,9 +22,9 @@ const regionOptions = [
desc: "替换火山引擎VKE集群中的TLS Secret证书",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToVKE extends AbstractTaskPlugin {
@TaskInput({
@@ -32,9 +32,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames]
from: [...CertApplyPluginNames],
},
required: true
required: true,
})
cert!: CertInfo;
@@ -46,9 +46,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine"
type: "volcengine",
},
required: true
required: true,
})
accessId!: string;
@@ -57,10 +57,10 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
helper: "VKE集群所在地域",
component: {
name: "a-select",
options: regionOptions
options: regionOptions,
},
value: "cn-beijing",
required: true
required: true,
})
regionId!: string;
@@ -71,7 +71,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
action: VolcengineDeployToVKE.prototype.onGetClusterList.name,
watches: ["accessId", "regionId"],
single: true,
required: true
required: true,
})
)
clusterId!: string;
@@ -83,11 +83,11 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
name: "a-select",
options: [
{ label: "公网", value: "Public" },
{ label: "私网", value: "Private" }
]
{ label: "私网", value: "Private" },
],
},
value: "Public",
required: true
required: true,
})
kubeconfigType!: "Public" | "Private";
@@ -95,9 +95,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
title: "命名空间",
value: "default",
component: {
placeholder: "命名空间"
placeholder: "命名空间",
},
required: true
required: true,
})
namespace!: string;
@@ -108,11 +108,11 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
name: "a-select",
options: [
{ label: "按Ingress替换", value: "ingress" },
{ label: "按Secret替换", value: "secret" }
]
{ label: "按Secret替换", value: "secret" },
],
},
value: "ingress",
required: true
required: true,
})
targetType!: "ingress" | "secret";
@@ -125,7 +125,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
show: ctx.compute(({form}) => form.targetType === 'ingress'),
required: ctx.compute(({form}) => form.targetType === 'ingress')
}
`
`,
})
ingressName!: string;
@@ -137,14 +137,14 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
name: "a-select",
vModel: "value",
mode: "tags",
open: false
open: false,
},
mergeScript: `
return {
show: ctx.compute(({form}) => form.targetType === 'secret'),
required: ctx.compute(({form}) => form.targetType === 'secret')
}
`
`,
})
secretName!: string | string[];
@@ -154,8 +154,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
value: false,
component: {
name: "a-switch",
vModel: "checked"
}
vModel: "checked",
},
})
createOnNotFound!: boolean;
@@ -165,8 +165,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
value: false,
component: {
name: "a-switch",
vModel: "checked"
}
vModel: "checked",
},
})
skipTLSVerify!: boolean;
@@ -188,7 +188,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
const k8sClient = new this.K8sClient({
kubeConfigStr: kubeconfig,
logger: this.logger,
skipTLSVerify: this.skipTLSVerify
skipTLSVerify: this.skipTLSVerify,
});
const secretNames = await this.getTargetSecretNames(k8sClient);
await this.patchCertSecret({ cert: this.cert, k8sClient, secretNames });
@@ -209,7 +209,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
return await client.getVkeService({ region: this.regionId });
}
@@ -222,8 +222,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
body: {
ClusterId: clusterId,
Type: this.kubeconfigType,
ValidDuration: 3600
}
ValidDuration: 3600,
},
});
const kubeconfigId = res.Result?.Id || res.Id;
if (!kubeconfigId) {
@@ -242,11 +242,11 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
Filter: {
ClusterIds: [clusterId],
Ids: [kubeconfigId],
Types: [this.kubeconfigType]
Types: [this.kubeconfigType],
},
PageNumber: 1,
PageSize: 10
}
PageSize: 10,
},
});
const items = res.Result?.Items || res.Items || [];
const item = items.find((it: any) => it.Id === kubeconfigId) || items[0];
@@ -268,8 +268,8 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
method: "POST",
body: {
ClusterId: clusterId,
Ids: [kubeconfigId]
}
Ids: [kubeconfigId],
},
});
this.logger.info(`已删除临时Kubeconfig:${kubeconfigId}`);
} catch (e) {
@@ -303,7 +303,9 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
const resource = message.match(/resource "([^"]+)"/)?.[1] || body.details?.kind || "目标资源";
const namespace = message.match(/namespace "([^"]+)"/)?.[1] || this.namespace;
const userText = granteeId ? `,用户ID:${granteeId}` : "";
return `VKE集群RBAC权限不足:当前火山引擎授权${userText}在集群:${this.getClusterId()} 的命名空间:${namespace} 没有操作 ${resource} 的权限。请在火山引擎 VKE 集群权限管理中,为该用户授予此命名空间的管理员权限,或授予包含 secrets get/create/update/patch 的自定义角色。原始错误:${JSON.stringify(body)}`;
return `VKE集群RBAC权限不足:当前火山引擎授权${userText}在集群:${this.getClusterId()} 的命名空间:${namespace} 没有操作 ${resource} 的权限。请在火山引擎 VKE 集群权限管理中,为该用户授予此命名空间的管理员权限,或授予包含 secrets get/create/update/patch 的自定义角色。原始错误:${JSON.stringify(
body
)}`;
}
private async getTargetSecretNames(k8sClient: any) {
@@ -315,7 +317,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
}
const ingressList = await k8sClient.getIngressList({
namespace: this.namespace
namespace: this.namespace,
});
const ingress = ingressList.items.find((item: any) => item.metadata.name === this.ingressName);
if (!ingress) {
@@ -341,13 +343,13 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
const body: any = {
data: {
"tls.crt": Buffer.from(cert.crt).toString("base64"),
"tls.key": Buffer.from(cert.key).toString("base64")
"tls.key": Buffer.from(cert.key).toString("base64"),
},
metadata: {
labels: {
certd: this.appendTimeSuffix("certd")
}
}
certd: this.appendTimeSuffix("certd"),
},
},
};
for (const secretName of secretNames) {
@@ -357,7 +359,7 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
namespace: this.namespace,
secretName,
body,
createOnNotFound: this.createOnNotFound
createOnNotFound: this.createOnNotFound,
});
this.logger.info(`VKE Secret已更新:${secretName}`);
}
@@ -378,13 +380,13 @@ export class VolcengineDeployToVKE extends AbstractTaskPlugin {
method: "POST",
body: {
PageNumber: 1,
PageSize: 100
}
PageSize: 100,
},
});
const list = res.Result?.Items || res.Items || [];
return list.map((item: any) => ({
label: `${item.Name || item.Id}<${item.Id}>`,
value: item.Id
value: item.Id,
}));
}
}
@@ -12,9 +12,9 @@ import { VolcengineClient } from "../ve-client.js";
desc: "部署至火山引擎视频点播",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class VolcengineDeployToVOD extends AbstractTaskPlugin {
@TaskInput({
@@ -22,28 +22,26 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"]
from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"],
},
required: true
required: true,
})
cert!: CertInfo | string;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "volcengine"
type: "volcengine",
},
required: true
required: true,
})
accessId!: string;
@TaskInput({
title: "区域",
helper: "选择火山引擎区域",
@@ -51,11 +49,11 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
name: "select",
options: [
{ value: "cn-north-1", label: "华北1(北京)" },
{ value: "ap-southeast-1", label: "东南亚1(新加坡)" }
]
{ value: "ap-southeast-1", label: "东南亚1(新加坡)" },
],
},
default: "cn-north-1",
required: true
required: true,
})
regionId!: string;
@@ -65,8 +63,8 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
helper: "选择要部署证书的点播空间",
action: VolcengineDeployToVOD.prototype.onGetSpaceList.name,
watches: ["accessId", "regionId"],
single:true,
required: true
single: true,
required: true,
})
)
spaceName!: string;
@@ -79,11 +77,11 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
vModel: "value",
options: [
{ value: "play", label: "点播加速域名" },
{ value: "image", label: "封面加速域名" }
]
{ value: "image", label: "封面加速域名" },
],
},
value: "play",
required: true
required: true,
})
domainType!: string;
@@ -93,24 +91,22 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
helper: "选择要部署证书的域名\n需要先在域名管理页面进行证书中心访问授权(即点击去配置SSL证书)",
action: VolcengineDeployToVOD.prototype.onGetDomainList.name,
watches: ["certDomains", "accessId", "spaceName", "domainType"],
required: true
required: true,
})
)
domainList!: string | string[];
async onInstance() {
}
async onInstance() {}
async execute(): Promise<void> {
this.logger.info("开始部署证书到火山引擎VOD");
if (!this.spaceName) {
throw new Error("SpaceName不能为空");
}
const access = await this.getAccess<VolcengineAccess>(this.accessId);
let certId = await this.uploadOrGetCertId(access);
const certId = await this.uploadOrGetCertId(access);
const service = await this.getVodService({ version: "2023-07-01", region: this.regionId });
const domains = Array.isArray(this.domainList) ? this.domainList : [this.domainList];
@@ -127,11 +123,11 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
HTTPS: {
Switch: true,
CertInfo: {
CertId: certId
}
}
}
}
CertId: certId,
},
},
},
},
});
this.logger.info(`部署域名${domain}证书成功`);
}
@@ -139,7 +135,6 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
this.logger.info("部署完成");
}
private async uploadOrGetCertId(access: VolcengineAccess) {
const certService = await this.getCertService(access);
let certId = this.cert;
@@ -148,7 +143,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
this.logger.info(`开始上传证书`);
certId = await certService.ImportCertificate({
certName: this.appendTimeSuffix("certd"),
cert: certInfo
cert: certInfo,
});
this.logger.info(`上传证书成功:${certId}`);
} else {
@@ -161,20 +156,19 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
return await client.getCertCenterService();
}
private async getVodService(req?: { version?: string, region?: string }) {
private async getVodService(req?: { version?: string; region?: string }) {
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = new VolcengineClient({
logger: this.logger,
access,
http: this.http
http: this.http,
});
return await client.getVodService(req);
@@ -188,7 +182,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
const res = await service.request({
action: "ListSpace",
body: {}
body: {},
});
const list = res.Result;
@@ -198,7 +192,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
return list.map((item: any) => {
return {
value: item.SpaceName,
label: `${item.SpaceName} (${item.Region})`
label: `${item.SpaceName} (${item.Region})`,
};
});
}
@@ -216,8 +210,8 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
action: "ListDomain",
query: {
SpaceName: this.spaceName,
DomainType: this.domainType
}
DomainType: this.domainType,
},
});
const instances = res.Result?.PlayInstanceInfo?.ByteInstances;
@@ -231,7 +225,7 @@ export class VolcengineDeployToVOD extends AbstractTaskPlugin {
if (domain.Domain) {
list.push({
value: domain.Domain,
label: domain.Domain
label: domain.Domain,
});
}
}
@@ -5,11 +5,11 @@ import { VolcengineAccess } from "../access.js";
import { VolcengineClient } from "../ve-client.js";
@IsTaskPlugin({
name: 'VolcengineUploadToCertCenter',
title: '火山引擎-上传证书至证书中心',
icon: 'svg:icon-volcengine',
name: "VolcengineUploadToCertCenter",
title: "火山引擎-上传证书至证书中心",
icon: "svg:icon-volcengine",
group: pluginGroups.volcengine.key,
desc: '上传证书至火山引擎证书中心',
desc: "上传证书至火山引擎证书中心",
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
@@ -18,10 +18,10 @@ import { VolcengineClient } from "../ve-client.js";
})
export class VolcengineUploadToCertCenter extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: 'output-selector',
name: "output-selector",
from: [...CertApplyPluginNames],
},
required: true,
@@ -31,47 +31,44 @@ export class VolcengineUploadToCertCenter extends AbstractTaskPlugin {
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'Access授权',
helper: '火山引擎AccessKeyId、AccessKeySecret',
title: "Access授权",
helper: "火山引擎AccessKeyId、AccessKeySecret",
component: {
name: 'access-selector',
type: 'volcengine',
name: "access-selector",
type: "volcengine",
},
required: true,
})
accessId!: string;
@TaskOutput({
title: '上传成功后的火山引擎证书Id',
title: "上传成功后的火山引擎证书Id",
})
volcengineCertId?: string;
async onInstance() {}
async execute(): Promise<void> {
this.logger.info('开始上传证书到证书中心');
this.logger.info("开始上传证书到证书中心");
const access = await this.getAccess<VolcengineAccess>(this.accessId);
const client = await this.getClient(access)
const service = await client.getCertCenterService()
const certInfo = this.cert
this.logger.info(`开始上传证书`)
const client = await this.getClient(access);
const service = await client.getCertCenterService();
const certInfo = this.cert;
this.logger.info(`开始上传证书`);
this.volcengineCertId = await service.ImportCertificate({
certName: this.appendTimeSuffix('certd'),
cert: certInfo
})
certName: this.appendTimeSuffix("certd"),
cert: certInfo,
});
this.logger.info(`上传完成:${this.volcengineCertId}`);
}
async getClient(access: VolcengineAccess) {
return new VolcengineClient({
return new VolcengineClient({
logger: this.logger,
access,
http:this.http
})
http: this.http,
});
}
}
new VolcengineUploadToCertCenter();
@@ -2,10 +2,10 @@ import { VolcengineAccess } from "./access.js";
import { HttpClient, ILogger } from "@certd/basic";
export type VolcengineOpts = {
access: VolcengineAccess
logger: ILogger
http: HttpClient
}
access: VolcengineAccess;
logger: ILogger;
http: HttpClient;
};
export class VolcengineClient {
opts: VolcengineOpts;
@@ -20,13 +20,13 @@ export class VolcengineClient {
const service = new CommonService({
serviceName: "certificate_service",
defaultVersion: "2024-10-01"
defaultVersion: "2024-10-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
service.setRegion("cn-beijing");
service.ImportCertificate = async (body: { certName: string, cert: any }) => {
service.ImportCertificate = async (body: { certName: string; cert: any }) => {
const { certName, cert } = body;
const res = await service.request({
action: "ImportCertificate",
@@ -36,9 +36,9 @@ export class VolcengineClient {
Repeatable: false,
CertificateInfo: {
CertificateChain: cert.crt,
PrivateKey: cert.key
}
}
PrivateKey: cert.key,
},
},
});
return res.Result.InstanceId || res.Result.RepeatId;
};
@@ -48,8 +48,8 @@ export class VolcengineClient {
action: "CertificateGetInstance",
method: "POST",
body: {
InstanceId: certificateId
}
InstanceId: certificateId,
},
});
return res.Result;
};
@@ -61,7 +61,7 @@ export class VolcengineClient {
const service = new CommonService({
serviceName: "clb",
defaultVersion: "2020-04-01"
defaultVersion: "2020-04-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -75,7 +75,7 @@ export class VolcengineClient {
const service = new CommonService({
serviceName: "live",
defaultVersion: "2023-01-01"
defaultVersion: "2023-01-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -84,12 +84,12 @@ export class VolcengineClient {
return service;
}
async getVodService(opts?: { version?: string, region?: string }) {
async getVodService(opts?: { version?: string; region?: string }) {
const CommonService = await this.getServiceCls();
const service = new CommonService({
serviceName: "vod",
defaultVersion: opts?.version || "2021-01-01"
defaultVersion: opts?.version || "2021-01-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -103,7 +103,7 @@ export class VolcengineClient {
const service = new CommonService({
serviceName: "alb",
defaultVersion: "2020-04-01"
defaultVersion: "2020-04-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -117,7 +117,7 @@ export class VolcengineClient {
const service = new CommonService({
serviceName: "vke",
defaultVersion: "2022-05-12"
defaultVersion: "2022-05-12",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -126,12 +126,12 @@ export class VolcengineClient {
return service;
}
async getDCDNService( opts?: { }) {
async getDCDNService(opts?: {}) {
const CommonService = await this.getServiceCls();
const service = new CommonService({
serviceName: "dcdn",
defaultVersion: "2023-01-01"
defaultVersion: "2023-01-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -141,14 +141,14 @@ export class VolcengineClient {
async getTOSService(opts: { region?: string }) {
const { TosClient } = await import("@volcengine/tos-sdk");
const client = new TosClient({
accessKeyId: this.opts.access.accessKeyId,
accessKeySecret: this.opts.access.secretAccessKey,
region: opts.region,
endpoint: `tos-${opts.region}.volces.com`
endpoint: `tos-${opts.region}.volces.com`,
});
return client;
}
@@ -157,7 +157,7 @@ export class VolcengineClient {
const service = new CommonService({
serviceName: "sts",
defaultVersion: "2018-01-01"
defaultVersion: "2018-01-01",
});
service.setAccessKeyId(this.opts.access.accessKeyId);
service.setSecretKey(this.opts.access.secretAccessKey);
@@ -174,29 +174,26 @@ export class VolcengineClient {
class CommonService extends Service {
Generic: any;
constructor(options: {
serviceName: string;
defaultVersion: string;
}) {
constructor(options: { serviceName: string; defaultVersion: string }) {
super(Object.assign({ host: "open.volcengineapi.com" }, options));
this.Generic = async (req: { action: string, body?: any, method?: string, query?: any ,version?:string}) => {
const { action, method, body, query,version } = req;
this.Generic = async (req: { action: string; body?: any; method?: string; query?: any; version?: string }) => {
const { action, method, body, query, version } = req;
return await this.fetchOpenAPI({
Action: action,
Version: version||options.defaultVersion,
Version: version || options.defaultVersion,
method: method as any,
headers: {
"content-type": "application/json"
"content-type": "application/json",
},
query: query || {},
data: body
data: body,
});
};
}
async request(req: { action: string, body?: any, method?: string, query?: any,version?:string }) {
async request(req: { action: string; body?: any; method?: string; query?: any; version?: string }) {
const res = await this.Generic(req);
if (res ==="Not Found"){
if (res === "Not Found") {
throw new Error(`${res} (检查method)`);
}
if (res.errorcode) {
@@ -212,7 +209,4 @@ export class VolcengineClient {
this.CommonService = CommonService;
return CommonService;
}
}
@@ -10,19 +10,18 @@ import { PageSearch } from "@certd/pipeline";
desc: "火山引擎DNS解析提供商",
accessType: "volcengine",
icon: "svg:icon-volcengine",
order:2,
order: 2,
})
export class VolcengineDnsProvider extends AbstractDnsProvider {
client: VolcengineDnsClient;
access!: VolcengineAccess;
async onInstance() {
this.access = this.ctx.access as VolcengineAccess
this.access = this.ctx.access as VolcengineAccess;
this.client = new VolcengineDnsClient({
access: this.access,
logger: this.logger,
http: this.http
http: this.http,
});
}
@@ -30,7 +29,7 @@ export class VolcengineDnsProvider extends AbstractDnsProvider {
* @param domain
*/
async getDomain(domain: string) {
const res = await this.client.findDomain(domain)
const res = await this.client.findDomain(domain);
if (res.Result.Zones && res.Result.Zones.length > 0) {
return res.Result.Zones[0];
@@ -38,7 +37,6 @@ export class VolcengineDnsProvider extends AbstractDnsProvider {
throw new Error(`域名${domain}不存在`);
}
async createRecord(options: CreateRecordOptions): Promise<any> {
const { fullRecord, hostRecord, value, type, domain } = options;
this.logger.info("添加域名解析:", fullRecord, value, domain);
@@ -48,9 +46,9 @@ export class VolcengineDnsProvider extends AbstractDnsProvider {
const body = {
ZID,
"Host": hostRecord,
"Type": type,
"Value": value
Host: hostRecord,
Type: type,
Value: value,
};
const res = await this.client.doRequest({
@@ -59,23 +57,22 @@ export class VolcengineDnsProvider extends AbstractDnsProvider {
region: "cn-beijing",
query: {
Action: "CreateRecord",
Version: "2018-08-01"
Version: "2018-08-01",
},
body
body,
});
return {
RecordID: res.Result.RecordID,
ZID: ZID
ZID: ZID,
};
}
async removeRecord(options: RemoveRecordOptions<any>): Promise<any> {
const record = options.recordRes;
const body = {
RecordID: record.RecordID
RecordID: record.RecordID,
};
await this.client.doRequest({
@@ -84,14 +81,14 @@ export class VolcengineDnsProvider extends AbstractDnsProvider {
region: "cn-beijing",
query: {
Action: "DeleteRecord",
Version: "2018-08-01"
Version: "2018-08-01",
},
body
body,
});
}
async getDomainListPage(page: PageSearch) {
return await this.client.getDomainList(page)
return await this.client.getDomainList(page);
}
}