mirror of https://github.com/certd/certd
perf: 更新k8s底层api库
parent
7b451bbf6e
commit
746bb9d385
|
@ -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",
|
||||||
|
|
|
@ -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,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
alter table cd_access alter column setting type text using setting::text;
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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`;
|
||||||
|
|
Loading…
Reference in New Issue