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

Commit e3a842b

Browse files
myan9starpit
authored andcommitted
fix(plugins/plugin-kubectl): event footer watching should also support named resources
Fixes #5180
1 parent d63a6f1 commit e3a842b

File tree

4 files changed

+46
-16
lines changed

4 files changed

+46
-16
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ export function getNamespaceForArgv(args: Arguments<KubeOptions>): string {
153153
return !ns ? '' : `-n ${ns}`
154154
}
155155

156+
/** @return the resource names array as expressed in the command line */
157+
export function getResourceNamesForArgv(kindFromArgv: string, args: Arguments<KubeOptions>): string[] {
158+
return args.argvNoOptions.slice(args.argvNoOptions.indexOf(kindFromArgv) + 1)
159+
}
160+
156161
export function getContext(args: Arguments<KubeOptions>) {
157162
return args.parsedOptions.context
158163
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ class StatusWatcher implements Abortable, Watcher {
402402
this.resourcesToWaitFor
403403
.map((_, idx) => {
404404
const { kind, name, namespace } = _
405-
const eventWatcher = new EventWatcher(this.args, this.command, kind, name, namespace, true, pusher)
405+
const eventWatcher = new EventWatcher(this.args, this.command, kind, [name], namespace, true, pusher)
406406
eventWatcher.init()
407407
this.ptyJob.push(eventWatcher)
408408

plugins/plugin-kubectl/src/controller/kubectl/watch/get-watch.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232

3333
import { kindPart } from '../fqn'
3434
import { getKind } from '../explain'
35-
import { formatOf, getLabel, getNamespace, KubeOptions, KubeExecOptions } from '../options'
35+
import { formatOf, getLabel, getNamespace, getResourceNamesForArgv, KubeOptions, KubeExecOptions } from '../options'
3636

3737
import { getCommandFromArgs } from '../../../lib/util/util'
3838
import { Pair, getNamespaceBreadcrumbs } from '../../../lib/view/formatTable'
@@ -100,7 +100,7 @@ export class EventWatcher implements Abortable, Watcher {
100100
private readonly args: Arguments,
101101
private readonly command: string,
102102
private readonly kindByUser: string,
103-
private readonly name: string,
103+
private readonly name: string[],
104104
private readonly namespace: string,
105105
private readonly watchOnly: boolean,
106106
private readonly pusher: WatchPusher
@@ -128,12 +128,15 @@ export class EventWatcher implements Abortable, Watcher {
128128
debug('rawData', rawData)
129129
this.eventLeftover = preprocessed.leftover === '\n' ? undefined : preprocessed.leftover
130130

131-
// format the row as `[ago] involvedObject.name: message`
132-
const sortedRows = preprocessed.rows.filter(notEmpty).sort((rowA, rowB) => {
133-
const lastSeenA = new Date(rowA[0].value).getTime()
134-
const lastSeenB = new Date(rowB[0].value).getTime()
135-
return lastSeenA - lastSeenB
136-
})
131+
// filter and format the row as `[ago] involvedObject.name: message`
132+
const sortedRows = preprocessed.rows
133+
.filter(notEmpty)
134+
.filter(row => !this.name || this.name.length === 0 || this.name.includes(row[1].value)) // filter the rows with `involvedObject.name` specified by `this.name`
135+
.sort((rowA, rowB) => {
136+
const lastSeenA = new Date(rowA[0].value).getTime()
137+
const lastSeenB = new Date(rowB[0].value).getTime()
138+
return lastSeenA - lastSeenB
139+
})
137140

138141
const agos = sortedRows.map(row => {
139142
const ago = Date.now() - new Date(row[0].value).getTime()
@@ -175,9 +178,7 @@ export class EventWatcher implements Abortable, Watcher {
175178

176179
public async init() {
177180
const fullKind = await getKind(this.command, this.args, this.kindByUser)
178-
const filter = this.name
179-
? `--field-selector=involvedObject.kind=${fullKind},involvedObject.name=${this.name}`
180-
: `--field-selector=involvedObject.kind=${fullKind}`
181+
const filter = `--field-selector=involvedObject.kind=${fullKind}`
181182

182183
const output = `--no-headers -o jsonpath='{.lastTimestamp}{"|"}{.involvedObject.name}{"|"}{.message}{"|"}{.metadata.name}{"|\\n"}'`
183184
const watch = this.watchOnly ? '--watch-only' : '-w'
@@ -422,12 +423,19 @@ class KubectlWatcher implements Abortable, Watcher {
422423
const cmd = getCommandFromArgs(this.args)
423424
const namespace = await getNamespace(this.args)
424425
const kindByUser = this.args.argvNoOptions[this.args.argvNoOptions.indexOf('get') + 1]
425-
const getWithResourceName = this.args.argvNoOptions.indexOf(kindByUser) !== this.args.argvNoOptions.length - 1
426426

427-
if (getWithResourceName || getLabel(this.args) || this.args.parsedOptions['field-selector']) {
428-
debug('event watch not support')
427+
if (getLabel(this.args) || this.args.parsedOptions['field-selector']) {
428+
debug('event watcher does not support label and field selector')
429429
} else {
430-
const eventWatcher = new EventWatcher(this.args, cmd, kindByUser, undefined, namespace, false, this.pusher)
430+
const eventWatcher = new EventWatcher(
431+
this.args,
432+
cmd,
433+
kindByUser,
434+
getResourceNamesForArgv(kindByUser, this.args),
435+
namespace,
436+
false,
437+
this.pusher
438+
)
431439
eventWatcher.init()
432440
this.ptyJob.push(eventWatcher)
433441
}

plugins/plugin-kubectl/src/test/k8s2/events-in-table.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ commands.forEach(command => {
7575
}
7676
})
7777

78+
it(`should watch with resource name and expect events`, async () => {
79+
try {
80+
const res = await CLI.command(`${command} get pods ${name} --watch ${inNamespace}`, this.app)
81+
console.log('wait for pod to come up')
82+
await this.app.client.waitUntil(async () => {
83+
return ReplExpect.okWithCustom({ selector: Selectors.BY_NAME(name) })(res)
84+
})
85+
86+
console.log('wait for events')
87+
await this.app.client.waitUntil(async () => {
88+
return (await currentEventCount(this.app, res.count)) > 0
89+
})
90+
} catch (err) {
91+
return Common.oops(this, true)(err)
92+
}
93+
})
94+
7895
deleteNS(this, ns)
7996
})
8097

0 commit comments

Comments
 (0)