Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit e351a5f

Browse files
committed
fix(plugins/plugin-kubectl): cache kind canonicalization lookup
Fixes #4489
1 parent 8fbdce5 commit e351a5f

File tree

1 file changed

+34
-11
lines changed
  • plugins/plugin-kubectl/src/controller/kubectl

1 file changed

+34
-11
lines changed

plugins/plugin-kubectl/src/controller/kubectl/explain.ts

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019 IBM Corporation
2+
* Copyright 2019-2020 IBM Corporation
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import Debug from 'debug'
1718
import { Arguments, Registrar, i18n } from '@kui-shell/core'
1819

1920
import flags from './flags'
@@ -23,6 +24,7 @@ import commandPrefix from '../command-prefix'
2324
import { isUsage, doHelp } from '../../lib/util/help'
2425

2526
const strings = i18n('plugin-kubectl')
27+
const debug = Debug('plugin-kubectl/controller/kubectl/explain')
2628

2729
function formatHref(href: string) {
2830
if (/api-conventions/.test(href) && !/sig-architecture/.test(href)) {
@@ -50,7 +52,7 @@ ${formatDocumentation(_[4])}
5052
}
5153
}
5254

53-
// alternate patterns to match against
55+
/** alternate patterns to match against */
5456
const kvd = /^KIND:\s+(\S+)\nVERSION:\s+(\S+)\n\nDESCRIPTION:\n(\s*DEPRECATED - )?([\s\S]+)/
5557
const kvdf = /^KIND:\s+(\S+)\nVERSION:\s+(\S+)\n\nDESCRIPTION:\n(\s*DEPRECATED - )?([\s\S]+)\n\nFIELDS:\n([\s\S]+)/
5658

@@ -127,22 +129,43 @@ ${isDeprecated ? `### Warnings\n${strings('This API Resource is deprecated')}` :
127129
return response
128130
}
129131

132+
/**
133+
* Cache of the getKind() lookup
134+
*
135+
*/
136+
const cache: Record<string, Promise<string>> = {}
137+
130138
/**
131139
* @param kindAsProvidedByUser e.g. pod or po
132140
* @return e.g. Pod
133141
*
134142
*/
135143
export async function getKind(command: string, args: Arguments, kindAsProvidedByUser: string): Promise<string> {
136-
try {
137-
const ourArgs = Object.assign({}, args, { command: `kubectl explain ${kindAsProvidedByUser}` })
138-
const explained = await doExecWithStdout(ourArgs, undefined, command)
139-
140-
return explained.match(/^KIND:\s+(.*)/)[1]
141-
} catch (err) {
142-
if (!/does not exist/i.test(err.message)) {
143-
console.error(`error explaining kind ${kindAsProvidedByUser}`, err)
144-
}
144+
if (!cache[kindAsProvidedByUser]) {
145+
// otherwise, we need to do a more expensive call to `kubectl`
146+
// eslint-disable-next-line no-async-promise-executor
147+
cache[kindAsProvidedByUser] = new Promise<string>(async (resolve, reject) => {
148+
try {
149+
const ourArgs = Object.assign({}, args, { command: `${command} explain ${kindAsProvidedByUser}` })
150+
const explained = await doExecWithStdout(ourArgs, undefined, command).catch(err => {
151+
// e.g. trying to explain CustomResourceDefinition.v1beta1.apiextensions.k8s.io
152+
// or a resource kind that does not exist
153+
debug(err)
154+
return `KIND: ${kindAsProvidedByUser}`
155+
})
156+
157+
const kindFromServer = explained.match(/^KIND:\s+(.*)/)[1]
158+
resolve(kindFromServer)
159+
} catch (err) {
160+
if (!/does not exist/i.test(err.message)) {
161+
console.error(`error explaining kind ${kindAsProvidedByUser}`, err)
162+
reject(err)
163+
}
164+
}
165+
})
145166
}
167+
168+
return cache[kindAsProvidedByUser]
146169
}
147170

148171
export default (registrar: Registrar) => {

0 commit comments

Comments
 (0)