🌳
pt0/deployF/k8sF/cliF/eptKubeCliF.mts
10import fs from 'fs'
16const getKubeConfigHelpText = (k8sCloudName: string, cluster_name: string, clusterVip?: string): string => {
17 const relPath = getKubeConfigRelPath(cluster_name)
18 if (k8sCloudName === 'harvester') {
19 const host = clusterVip || '<clusterVip>'
20 return `1) Goto https://${host}/dashboard/harvester/c/local/support\n2) Download KubeConfig to ${relPath}`
21 }
22 if (k8sCloudName === 'digitalocean') {
23 return `Download kubeconfig from DigitalOcean dashboard to ${relPath}`
24 }
25 if (k8sCloudName === 'vultr') {
26 return `Download kubeconfig from Vultr dashboard to ${relPath}`
27 }
28 return `Please download kubeconfig from ${k8sCloudName} dashboard to ${relPath}`
31export const noOutCmdCtx = genContext()
33type CliActionParams = { cluster_name: string; args: string[]; kubeConfigPath: string }
35const help = async ({ cluster_name, args, kubeConfigPath }: CliActionParams) => {
37 const targetAction = args[0] as keyof ReturnType<typeof getPtActionsH> | undefined
39 const ptActionsH = getPtActionsH()
40 if (targetAction && ptActionsH[targetAction]) {
41 console.log(`${targetAction}: ${ptActionsH[targetAction].cliDescript}`)
42 return
43 }
45 const kubectlArgs = targetAction ? ['help', targetAction] : ['help']
46 const result = await do2ExecFile({
47 cmdA: ['kubectl', ...kubectlArgs],
48 opts: { env: { ...process.env, KUBECONFIG: kubeConfigPath } }
49 })
50 process.stdout.write(result.stdout)
51 if (result.stderr) process.stderr.write(result.stderr)
53 if (!targetAction) {
54 const ptActionsLines = Object.entries(ptActionsH).map(([name, action]) => ` ${name.padEnd(16)}${action.cliDescript}`)
55 console.log(`\nptActions:\n${ptActionsLines.join('\n')}`)
56 }
59help.cliDescript = '[action] shows more help'
61const getPtActionsH = () => ({ ...ptActionsModule, help })
63// writes LAN-resolved kubeconfig to a temp file for kubectl usage (original untouched)
64export const getResolvedKubeConfigPath = async (cluster_name: string, origPath?: string) => {
65 origPath ||= getKubeConfigPath(cluster_name)
66 return getResolvedKubeConfigPathCore(cluster_name, origPath)
69const getResolvedKubeConfigPathCore = async (cluster_name: string, origPath: string) => {
70 const origContent = fs.readFileSync(origPath, 'utf8')
71 const resolved = await rewriteKcHostForLan({klusterCfgStr: origContent, cluster_name} as any)
72 const serverMatch = resolved.match(/server:\s*"?https?:\/\/([^\s/",:]+)/)
73 // if (serverMatch) console.log(`kubehost: ${serverMatch[1]}`)
74 if (resolved === origContent) return origPath
75 const resolvedPath = `${secretsDir}/${cluster_name}-resolved.yaml`
76 fs.writeFileSync(resolvedPath, resolved)
77 return resolvedPath
80export const eptKubeCli = async (argv: string[]) => {
81 const cluster_name = argv[0]
82 const otherArgs = argv.slice(1)
83 const origKubeConfigPath = getKubeConfigPath(cluster_name)
85 if (!fs.existsSync(origKubeConfigPath)) {
86 const { k8sCloudName, clusterVip } = getCurKlusterCfg(cluster_name) as { k8sCloudName?: string, clusterVip?: string }
87 assertDefined(k8sCloudName)
89 filePath: absPathToPtPath(origKubeConfigPath),
90 helpText: getKubeConfigHelpText(k8sCloudName, cluster_name, clusterVip),
91 })
92 }
93 const kubeConfigPath = await getResolvedKubeConfigPathCore(cluster_name, origKubeConfigPath)
95 const mainArg = otherArgs[0]
96 const actionArgs = otherArgs.slice(1)
98 const actionsH = getPtActionsH()
99 const actionFnc = mainArg in actionsH ? actionsH[mainArg as keyof typeof actionsH] : undefined
100 if (actionFnc) {
101 await actionFnc({ cluster_name, args: actionArgs, kubeConfigPath })
102 return
103 }
105 if (!mainArg) {
106 await help({ cluster_name, args: [], kubeConfigPath })
107 return
108 }
110 const { kubeTlsInsecure = false } = getCurKlusterCfg(cluster_name) as { kubeTlsInsecure?: boolean }
112 const cmdA = [
113 'kubectl',
114 kubeTlsInsecure && '--insecure-skip-tls-verify',
115 ...otherArgs,
116 ].filter(Boolean) as string[]
118 const opts = {
119 env: { ...process.env, KUBECONFIG: kubeConfigPath },
120 timeout: mainArg === 'port-forward' ? undefined : getKubeTimeoutSec(cluster_name) * 1000,
121 }
123 if (mainArg === 'logs') {
124 const result = await runLogsWithRetry({ kubeConfigPath, cmdA, noOutCmd: true })
125 if (noOutCmdCtx.getStore()) return result
126 return
127 }
129 const result = await do2ExecFile({ cmdA, opts })
131 if (result.stderr && isMinikubeConnectionRefused(result.stderr)) {
132 const { k8sCloudName } = getCurKlusterCfg(cluster_name) as { k8sCloudName?: string }
133 if (k8sCloudName === 'minikube') {
135 return
136 }
137 }
139 if (noOutCmdCtx.getStore()) {
140 if (!result.isSuccess) return result
141 return result
142 }
144 process.stdout.write(result.stdout)
145 if (result.stderr) process.stderr.write(result.stderr)
146 if (!result.isSuccess) throw new Error(`!eptKubeCli ${cmdA.join(' ')} code=${result.code}`)