Compare commits

...

5 Commits

Author SHA1 Message Date
xiaojunnuo
69e6f2362e chore: 2025-07-23 00:12:51 +08:00
xiaojunnuo
ab84835362 perf: 部署到k8s,tke,ack忽悠证书校验 2025-07-22 17:03:52 +08:00
xiaojunnuo
41ce8489dc perf: 首页增加更新日志按钮 2025-07-22 16:42:17 +08:00
xiaojunnuo
edf089ec9e build: publish 2025-07-22 12:27:21 +08:00
xiaojunnuo
0ae9a3605c build: trigger build image 2025-07-22 12:27:10 +08:00
20 changed files with 80 additions and 33 deletions

View File

@@ -1 +1 @@
2
12:27

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
### Bug Fixes
* 安全更新,备份数据库插件仅限管理员运行 ([13dfca1](https://github.com/certd/certd/commit/13dfca1749275526c82465a17c482b607c820fdd))
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
### Bug Fixes

View File

@@ -69,5 +69,5 @@
"bugs": {
"url": "https://github.com/publishlab/node-acme-client/issues"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -45,5 +45,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -44,5 +44,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -24,5 +24,5 @@
"prettier": "^2.8.8",
"tslib": "^2.8.1"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -31,5 +31,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -61,5 +61,5 @@
"fetch"
]
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -32,5 +32,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -1 +1 @@
export * from './lib/k8s.client.js';
export * from "./lib/k8s.client.js";

View File

@@ -1,7 +1,7 @@
import { CoreV1Api, KubeConfig, NetworkingV1Api, V1Ingress, V1Secret } from '@kubernetes/client-node';
import dns from 'dns';
import { ILogger } from '@certd/basic';
import _ from 'lodash-es';
import { CoreV1Api, KubeConfig, NetworkingV1Api, V1Ingress, V1Secret } from "@kubernetes/client-node";
import dns from "dns";
import { ILogger } from "@certd/basic";
import _ from "lodash-es";
export type K8sClientOpts = {
kubeConfigStr: string;
@@ -9,6 +9,7 @@ export type K8sClientOpts = {
//{ [domain]:{ip:'xxx.xx.xxx'} }
//暂时没用
lookup?: any;
skipTLSVerify?: boolean;
};
export class K8sClient {
kubeconfig!: KubeConfig;
@@ -16,10 +17,12 @@ export class K8sClient {
lookup!: (hostnameReq: any, options: any, callback: any) => void;
client!: CoreV1Api;
logger: ILogger;
skipTLSVerify?: boolean;
constructor(opts: K8sClientOpts) {
this.kubeConfigStr = opts.kubeConfigStr;
this.logger = opts.logger;
this.setLookup(opts.lookup);
this.skipTLSVerify = opts.skipTLSVerify;
this.init();
}
@@ -27,6 +30,18 @@ export class K8sClient {
const kubeconfig = new KubeConfig();
kubeconfig.loadFromString(this.kubeConfigStr);
this.kubeconfig = kubeconfig;
try {
if (this.skipTLSVerify == true) {
for (const cluster of kubeconfig.getClusters()) {
// @ts-ignore
cluster["skipTLSVerify"] = this.skipTLSVerify;
}
}
} catch (e) {
this.logger.warn("skipTLSVerify error", e);
}
this.client = kubeconfig.makeApiClient(CoreV1Api);
// const reqOpts = { kubeconfig, request: {} } as any;
@@ -47,9 +62,9 @@ export class K8sClient {
return;
}
this.lookup = (hostnameReq: any, options: any, callback: any) => {
this.logger.info('custom lookup', hostnameReq, localRecords);
this.logger.info("custom lookup", hostnameReq, localRecords);
if (localRecords[hostnameReq]) {
this.logger.info('local record', hostnameReq, localRecords[hostnameReq]);
this.logger.info("local record", hostnameReq, localRecords[hostnameReq]);
callback(null, localRecords[hostnameReq].ip, 4);
} else {
dns.lookup(hostnameReq, options, callback);
@@ -63,7 +78,7 @@ export class K8sClient {
* @returns secretsList
*/
async getSecrets(opts: { namespace: string }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
return await this.client.listNamespacedSecret(namespace);
}
@@ -73,9 +88,9 @@ export class K8sClient {
* @returns {Promise<*>}
*/
async createSecret(opts: { namespace: string; body: V1Secret }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const created = await this.client.createNamespacedSecret(namespace, opts.body);
this.logger.info('new secrets:', opts.body);
this.logger.info("new secrets:", opts.body);
return created.body;
}
@@ -89,24 +104,24 @@ export class K8sClient {
// }
async patchSecret(opts: { namespace: string; secretName: string; body: V1Secret }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const secretName = opts.secretName;
if (secretName == null) {
throw new Error('secretName 不能为空');
throw new Error("secretName 不能为空");
}
this.logger.info('patch secret:', secretName, namespace);
this.logger.info("patch secret:", secretName, namespace);
const oldSecret = await this.client.readNamespacedSecret(secretName, namespace);
const newSecret = _.merge(oldSecret.body, opts.body);
const res = await this.client.replaceNamespacedSecret(secretName, namespace, newSecret);
this.logger.info('secret updated');
this.logger.info("secret updated");
return res.body;
}
async getIngressList(opts: { namespace: string }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
const res = await client.listNamespacedIngress(namespace);
this.logger.info('ingress list get:', res.body);
this.logger.info("ingress list get:", res.body);
return res.body;
}
@@ -122,17 +137,17 @@ export class K8sClient {
// }
async patchIngress(opts: { namespace: string; ingressName: string; body: V1Ingress }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const ingressName = opts.ingressName;
if (!ingressName) {
throw new Error('ingressName 不能为空');
throw new Error("ingressName 不能为空");
}
this.logger.info('patch ingress:', ingressName, namespace);
this.logger.info("patch ingress:", ingressName, namespace);
const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
const oldIngress = await client.readNamespacedIngress(ingressName, namespace);
const newIngress = _.merge(oldIngress.body, opts.body);
const res = await client.replaceNamespacedIngress(ingressName, namespace, newIngress);
this.logger.info('ingress patched', opts.body);
this.logger.info("ingress patched", opts.body);
return res;
}
}

View File

@@ -61,5 +61,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -46,5 +46,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -43,5 +43,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -53,5 +53,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "085bdf5cfa9140903611aa12cdd2542d05aba321"
"gitHead": "7f9c4e52ac5c3837b251d3b2508457ce802e11cb"
}

View File

@@ -280,6 +280,10 @@ function openUpgrade() {
},
};
const productListUrl = computed(() => {
return `http://localhost:1017/subject/#/product/list?appKey=${settingStore.installInfo.appKey}&subjectId=${settingStore.installInfo.siteId}`;
});
const modalRef = modal.confirm({
title,
async onOk() {

View File

@@ -78,6 +78,7 @@ export default {
runCount: "Run Count",
expiringCerts: "Soon-to-Expire Certificates",
supportedTasks: "Overview of Supported Deployment Tasks",
changeLog: "Change Log",
},
steps: {
createPipeline: "Create Certificate Pipeline",

View File

@@ -84,6 +84,7 @@ export default {
runCount: "运行次数",
expiringCerts: "最快到期证书",
supportedTasks: "已支持的部署任务总览",
changeLog: "更新日志",
},
steps: {
createPipeline: "创建证书流水线",

View File

@@ -29,6 +29,10 @@
</a-tag>
</a-badge>
<a-divider type="vertical" />
<a-tag color="blue" class="flex-inline pointer mr-0" @click="openChangeLogUrl()">
{{ t("certd.dashboard.changeLog") }}
</a-tag>
<a-divider type="vertical" />
<vip-button mode="nav" style="font-size: 12px"></vip-button>
</template>
<template v-if="settingsStore.isComm">
@@ -255,6 +259,9 @@ onMounted(async () => {
function openUpgradeUrl() {
window.open("https://certd.docmirror.cn/guide/install/upgrade.html");
}
function openChangeLogUrl() {
window.open("https://certd.docmirror.cn/guide/changelogs/CHANGELOG.html");
}
</script>
<style lang="less">

View File

@@ -136,6 +136,18 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
ingressName!: string | string[];
@TaskInput({
title: "忽略证书校验",
required: false,
helper: "是否忽略证书校验",
component: {
name: "a-switch",
vModel: "checked",
}
})
skipTLSVerify!:boolean
// @TaskInput({ title: "集群内网ip", helper: "如果开启了外网的话,无需设置" })
// clusterIp!: string;
@@ -163,7 +175,8 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
this.logger.info("kubeconfig已成功获取");
const k8sClient = new this.K8sClient({
kubeConfigStr,
logger: this.logger
logger: this.logger,
skipTLSVerify: this.skipTLSVerify,
});
// if (this.clusterIp != null) {
// if (!this.clusterDomain) {