perf: 更新k8s底层api库

pull/148/head
xiaojunnuo 2024-08-14 15:10:55 +08:00
parent 7b451bbf6e
commit 746bb9d385
8 changed files with 85 additions and 64 deletions

View File

@ -13,8 +13,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"kubernetes-client": "^9.0.0", "@kubernetes/client-node": "0.21.0"
"shelljs": "^0.8.5"
}, },
"devDependencies": { "devDependencies": {
"@certd/pipeline": "^1.23.1", "@certd/pipeline": "^1.23.1",

View File

@ -1,32 +1,40 @@
import kubernetesClient from 'kubernetes-client'; import { KubeConfig, CoreV1Api, V1Secret, NetworkingV1Api, V1Ingress } from '@kubernetes/client-node';
//@ts-ignore
import dns from 'dns'; import dns from 'dns';
import { ILogger } from '@certd/pipeline'; import { ILogger } from '@certd/pipeline';
//@ts-ignore export type K8sClientOpts = {
const { KubeConfig, Client, Request } = kubernetesClient;
export class K8sClient {
kubeConfigStr: string; kubeConfigStr: string;
lookup!: any;
client!: any;
logger: ILogger; logger: ILogger;
constructor(kubeConfigStr: string, logger: ILogger) { //{ [domain]:{ip:'xxx.xx.xxx'} }
this.kubeConfigStr = kubeConfigStr; //暂时没用
this.logger = logger; lookup?: any;
};
export class K8sClient {
kubeconfig!: KubeConfig;
kubeConfigStr: string;
lookup!: (hostnameReq: any, options: any, callback: any) => void;
client!: CoreV1Api;
logger: ILogger;
constructor(opts: K8sClientOpts) {
this.kubeConfigStr = opts.kubeConfigStr;
this.logger = opts.logger;
this.setLookup(opts.lookup);
this.init(); this.init();
} }
init() { init() {
const kubeconfig = new KubeConfig(); const kubeconfig = new KubeConfig();
kubeconfig.loadFromString(this.kubeConfigStr); kubeconfig.loadFromString(this.kubeConfigStr);
const reqOpts = { kubeconfig, request: {} } as any; this.kubeconfig = kubeconfig;
if (this.lookup) { this.client = kubeconfig.makeApiClient(CoreV1Api);
reqOpts.request.lookup = this.lookup;
}
const backend = new Request(reqOpts); // const reqOpts = { kubeconfig, request: {} } as any;
this.client = new Client({ backend, version: '1.13' }); // if (this.lookup) {
// reqOpts.request.lookup = this.lookup;
// }
//
// const backend = new Request(reqOpts);
// this.client = new Client({ backend, version: '1.13' });
} }
/** /**
@ -34,6 +42,9 @@ export class K8sClient {
* @param localRecords { [domain]:{ip:'xxx.xx.xxx'} } * @param localRecords { [domain]:{ip:'xxx.xx.xxx'} }
*/ */
setLookup(localRecords: { [key: string]: { ip: string } }) { setLookup(localRecords: { [key: string]: { ip: string } }) {
if (localRecords == null) {
return;
}
this.lookup = (hostnameReq: any, options: any, callback: any) => { 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]) { if (localRecords[hostnameReq]) {
@ -43,7 +54,6 @@ export class K8sClient {
dns.lookup(hostnameReq, options, callback); dns.lookup(hostnameReq, options, callback);
} }
}; };
this.init();
} }
/** /**
@ -51,9 +61,9 @@ export class K8sClient {
* @param opts = {namespace:default} * @param opts = {namespace:default}
* @returns secretsList * @returns secretsList
*/ */
async getSecret(opts: { namespace: string }) { async getSecrets(opts: { namespace: string }) {
const namespace = opts.namespace || 'default'; const namespace = opts.namespace || 'default';
return await this.client.api.v1.namespaces(namespace).secrets.get(); return await this.client.listNamespacedSecret(namespace);
} }
/** /**
@ -61,59 +71,61 @@ export class K8sClient {
* @param opts {namespace:default, body:yamlStr} * @param opts {namespace:default, body:yamlStr}
* @returns {Promise<*>} * @returns {Promise<*>}
*/ */
async createSecret(opts: any) { async createSecret(opts: { namespace: string; body: V1Secret }) {
const namespace = opts.namespace || 'default'; const namespace = opts.namespace || 'default';
const created = await this.client.api.v1.namespaces(namespace).secrets.post({ const created = await this.client.createNamespacedSecret(namespace, opts.body);
body: opts.body, this.logger.info('new secrets:', created.body);
}); return created.body;
this.logger.info('new secrets:', created);
return created;
} }
async updateSecret(opts: any) { // async updateSecret(opts: any) {
// const namespace = opts.namespace || 'default';
// const secretName = opts.secretName;
// if (secretName == null) {
// throw new Error('secretName 不能为空');
// }
// return await this.client.replaceNamespacedSecret(secretName, namespace, opts.body);
// }
async patchSecret(opts: { namespace: string; secretName: string; body: V1Secret }) {
const namespace = opts.namespace || 'default'; const namespace = opts.namespace || 'default';
const secretName = opts.secretName; const secretName = opts.secretName;
if (secretName == null) { if (secretName == null) {
throw new Error('secretName 不能为空'); throw new Error('secretName 不能为空');
} }
return await this.client.api.v1.namespaces(namespace).secrets(secretName).put({ const res = await this.client.patchNamespacedSecret(secretName, namespace, opts.body);
body: opts.body, this.logger.info('secret patched:', res.body);
}); return res.body;
} }
async patchSecret(opts: any) { async getIngressList(opts: { namespace: string }) {
const namespace = opts.namespace || 'default'; const namespace = opts.namespace || 'default';
const secretName = opts.secretName; const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
if (secretName == null) { const res = await client.listNamespacedIngress(namespace);
throw new Error('secretName 不能为空'); this.logger.info('ingress list get:', res.body);
} return res.body;
return await this.client.api.v1.namespaces(namespace).secrets(secretName).patch({
body: opts.body,
});
} }
async getIngressList(opts: any) { // async getIngress(opts: { namespace: string; ingressName: string }) {
const namespace = opts.namespace || 'default'; // const namespace = opts.namespace || 'default';
return await this.client.apis.extensions.v1beta1.namespaces(namespace).ingresses.get(); // const ingressName = opts.ingressName;
} // if (!ingressName) {
// throw new Error('ingressName 不能为空');
// }
// const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
// const res = await client.listNamespacedIngress();
// return await this.client.apis.extensions.v1beta1.namespaces(namespace).ingresses(ingressName).get();
// }
async getIngress(opts: any) { async patchIngress(opts: { namespace: string; ingressName: string; body: V1Ingress }) {
const namespace = opts.namespace || 'default'; const namespace = opts.namespace || 'default';
const ingressName = opts.ingressName; const ingressName = opts.ingressName;
if (!ingressName) { if (!ingressName) {
throw new Error('ingressName 不能为空'); throw new Error('ingressName 不能为空');
} }
return await this.client.apis.extensions.v1beta1.namespaces(namespace).ingresses(ingressName).get(); const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
} const res = await client.patchNamespacedIngress(ingressName, namespace, opts.body);
this.logger.info('ingress patched:', res.body);
async patchIngress(opts: any) { return res;
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,
});
} }
} }

View File

@ -97,7 +97,7 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
this.http = this.ctx.http; this.http = this.ctx.http;
this.lastStatus = this.ctx.lastStatus as Step; this.lastStatus = this.ctx.lastStatus as Step;
if (this.legoEabAccessId) { if (this.legoEabAccessId) {
this.eab = await this.ctx.accessService.getById(this.legoEabAccessId); this.eab = await this.accessService.getById(this.legoEabAccessId);
} }
} }
async onInit(): Promise<void> {} async onInit(): Promise<void> {}

View File

@ -0,0 +1 @@
alter table cd_access alter column setting type text using setting::text;

View File

@ -4,3 +4,4 @@ export * from './plugin-tencent/index.js';
export * from './plugin-host/index.js'; export * from './plugin-host/index.js';
export * from './plugin-huawei/index.js'; export * from './plugin-huawei/index.js';
export * from './plugin-demo/index.js'; export * from './plugin-demo/index.js';
export * from './plugin-other/index.js';

View File

@ -115,7 +115,10 @@ export class DeployCertToAliyunAckIngressPlugin extends AbstractTaskPlugin {
const kubeConfigStr = await this.getKubeConfig(client, clusterId, isPrivateIpAddress); const kubeConfigStr = await this.getKubeConfig(client, clusterId, isPrivateIpAddress);
this.logger.info('kubeconfig已成功获取'); this.logger.info('kubeconfig已成功获取');
const k8sClient = new K8sClient(kubeConfigStr, this.logger); const k8sClient = new K8sClient({
kubeConfigStr,
logger: this.logger,
});
const ingressType = ingressClass || 'qcloud'; const ingressType = ingressClass || 'qcloud';
if (ingressType === 'qcloud') { if (ingressType === 'qcloud') {
throw new Error('暂未实现'); throw new Error('暂未实现');
@ -128,7 +131,7 @@ export class DeployCertToAliyunAckIngressPlugin extends AbstractTaskPlugin {
// await this.restartIngress({ k8sClient, props }) // await this.restartIngress({ k8sClient, props })
} }
async restartIngress(options: { k8sClient: any }) { async restartIngress(options: { k8sClient: K8sClient }) {
const { k8sClient } = options; const { k8sClient } = options;
const { namespace } = this; const { namespace } = this;
@ -141,10 +144,10 @@ export class DeployCertToAliyunAckIngressPlugin extends AbstractTaskPlugin {
}; };
const ingressList = await k8sClient.getIngressList({ namespace }); const ingressList = await k8sClient.getIngressList({ namespace });
console.log('ingressList:', ingressList); console.log('ingressList:', ingressList);
if (!ingressList || !ingressList.body || !ingressList.body.items) { if (!ingressList || !ingressList.items) {
return; return;
} }
const ingressNames = ingressList.body.items const ingressNames = ingressList.items
.filter((item: any) => { .filter((item: any) => {
if (!item.spec.tls) { if (!item.spec.tls) {
return false; return false;
@ -165,7 +168,7 @@ export class DeployCertToAliyunAckIngressPlugin extends AbstractTaskPlugin {
} }
} }
async patchNginxCertSecret(options: { cert: any; k8sClient: any }) { async patchNginxCertSecret(options: { cert: CertInfo; k8sClient: K8sClient }) {
const { cert, k8sClient } = options; const { cert, k8sClient } = options;
const crt = cert.crt; const crt = cert.crt;
const key = cert.key; const key = cert.key;

View File

@ -9,6 +9,8 @@ export class K8sAccess {
@AccessInput({ @AccessInput({
title: 'kubeconfig', title: 'kubeconfig',
component: { component: {
name: 'a-textarea',
vModel: 'value',
placeholder: 'kubeconfig', placeholder: 'kubeconfig',
}, },
required: true, required: true,

View File

@ -97,7 +97,10 @@ export class DeployCertToTencentTKEIngressPlugin extends AbstractTaskPlugin {
const kubeConfigStr = await this.getTkeKubeConfig(tkeClient, this.clusterId); const kubeConfigStr = await this.getTkeKubeConfig(tkeClient, this.clusterId);
this.logger.info('kubeconfig已成功获取'); this.logger.info('kubeconfig已成功获取');
const k8sClient = new K8sClient(kubeConfigStr, this.logger); const k8sClient = new K8sClient({
kubeConfigStr,
logger: this.logger,
});
if (this.clusterIp != null) { if (this.clusterIp != null) {
if (!this.clusterDomain) { if (!this.clusterDomain) {
this.clusterDomain = `${this.clusterId}.ccs.tencent-cloud.com`; this.clusterDomain = `${this.clusterId}.ccs.tencent-cloud.com`;