@@ -19,10 +19,11 @@ type Selector = {
1919} ;
2020
2121const pathRE = new RegExp (
22- '(?<prefix>k8s|search|api-resource)' +
23- '/((ns/(?<namespace>[^/]+))|cluster|all-namespaces)' +
24- '(/(?<resource>[^/]+)(/(?<name>([^/]+))(?<events>/events)?)?)?' ,
22+ '(?<prefix>k8s|search|api-resource)' + // prefix
23+ '/((ns/(?<namespace>[^/]+))|cluster|all-namespaces)' + // /namespace
24+ '(/(?<resource>[^/]+)(/(?<name>([^/]+))(?<events>/events)?)?)?' , // [/resource[/name[/events]]]
2525) ;
26+
2627const versionRE = / (?< version > v [ 0 - 9 ] + ( ( a l p h a | b e t a ) [ 0 - 9 ] * ) ? ) / ;
2728const classRE = new RegExp ( `^(?<kind>[^./]+)(\\.${ versionRE . source } )?(.(?<group>[^/]*))?$` ) ;
2829
@@ -55,13 +56,30 @@ export class K8sDomain extends Domain {
5556 const resource = g . resource || link . searchParams . get ( 'kind' ) ;
5657 const model = findResource ( resource ) ;
5758 if ( ! model ?. kind ) throw this . badLink ( link , `unknown resource: ${ resource } ` ) ;
59+ // api-resource is a resource type not a named instance, ignore the name part of the URL.
5860 const name = g . prefix === 'api-resource' ? undefined : g . name ;
59- const data = {
60- namespace : g . namespace ,
61- name,
62- labels : K8sDomain . parseSelector ( link . searchParams . get ( 'labels' ) ) || undefined ,
63- } ;
64- return this . modelClass ( model ) . query ( JSON . stringify ( data ) ) ;
61+ if ( g . events ) {
62+ // Special case for /events, query for events with this resource as involved object
63+ const event = eventModel ( ) ;
64+ const about = eventAboutField ( event ) ;
65+ const apiVersion = `${ model . apiGroup ? `${ model . apiGroup } /` : '' } ${ model . apiVersion || 'v1' } ` ;
66+ const data = {
67+ fields : {
68+ [ `${ about } .namespace` ] : g . namespace ,
69+ [ `${ about } .name` ] : name ,
70+ [ `${ about } .apiVersion` ] : apiVersion ,
71+ [ `${ about } .kind` ] : model . kind ,
72+ } ,
73+ } ;
74+ return this . modelClass ( event ) . query ( JSON . stringify ( data ) ) ;
75+ } else {
76+ const data = {
77+ namespace : g . namespace ,
78+ name,
79+ labels : K8sDomain . parseSelector ( link . searchParams . get ( 'labels' ) ) || undefined ,
80+ } ;
81+ return this . modelClass ( model ) . query ( JSON . stringify ( data ) ) ;
82+ }
6583 }
6684
6785 // NOTE: k8s queries don't support query constraints, so neither do console k8s URIs.
@@ -78,7 +96,7 @@ export class K8sDomain extends Domain {
7896 let name = selector . name ;
7997 let events = '' ;
8098 if ( isEvent ( model ) ) {
81- // Special case for events, use involved object with '/events' modifier.
99+ // Special case for events, generate URL of involved object with '/events' modifier.
82100 const eventClass = this . modelClass ( model ) ;
83101 const about = eventAboutField ( model ) ;
84102 const [ group , version ] = parseAPIVersion ( selector . fields [ `${ about } .apiVersion` ] ) ;
@@ -134,6 +152,12 @@ function isEvent(m: Model): boolean {
134152 ) ;
135153}
136154
155+ // Returns an event resource model that is supported by the cluster.
156+ // Prefer the older version as there are still many older clusters out there.
157+ function eventModel ( ) : Model {
158+ return findGVK ( '' , EVENT . version , EVENT . kind ) || findGVK ( EVENT . group , EVENT . version , EVENT . kind ) ;
159+ }
160+
137161function eventAboutField ( m : Model ) : string {
138162 return m ?. apiGroup === EVENT . group ? 'regarding' : 'involvedObject' ;
139163}
0 commit comments