1- import { SingleYAMLDocument } from '../parser/yamlParser07' ;
21import { JSONDocument } from '../parser/jsonDocument' ;
2+ import { SingleYAMLDocument } from '../parser/yamlParser07' ;
33
44import { ResolvedSchema } from 'vscode-json-languageservice/lib/umd/services/jsonSchemaService' ;
55import { JSONSchema } from '../jsonSchema' ;
6+ import { BASE_KUBERNETES_SCHEMA_URL } from '../utils/schemaUrls' ;
67
78/**
8- * Retrieve schema by auto-detecting the Kubernetes GroupVersionKind (GVK) from the document.
9- * If there is no definition for the GVK in the main kubernetes schema,
10- * the schema is then retrieved from the CRD catalog.
11- * Public for testing purpose, not part of the API.
12- * @param doc
13- * @param crdCatalogURI The URL of the CRD catalog to retrieve the schema from
14- * @param kubernetesSchema The main kubernetes schema, if it includes a definition for the GVK it will be used
9+ * Attempt to retrieve the schema for a given YAML document based on the Kubernetes GroupVersionKind (GVK).
10+ *
11+ * First, checks for a schema for a matching builtin resource, then it checks for a schema for a CRD.
12+ *
13+ * @param doc the yaml document being validated
14+ * @param kubernetesSchema the resolved copy of the Kubernetes builtin
15+ * @param crdCatalogURI the catalog uri to use to find schemas for custom resource definitions
16+ * @returns a schema uri, or undefined if no specific schema can be identified
1517 */
16- export function autoDetectKubernetesSchemaFromDocument (
18+ export function autoDetectKubernetesSchema (
1719 doc : SingleYAMLDocument | JSONDocument ,
18- crdCatalogURI : string ,
19- kubernetesSchema : ResolvedSchema
20+ kubernetesSchema : ResolvedSchema ,
21+ crdCatalogURI : string
2022) : string | undefined {
21- const res = getGroupVersionKindFromDocument ( doc ) ;
22- if ( ! res ) {
23+ const gvk = getGroupVersionKindFromDocument ( doc ) ;
24+ if ( ! gvk || ! gvk . group || ! gvk . version || ! gvk . kind ) {
2325 return undefined ;
2426 }
25- const { group , version , kind } = res ;
26- if ( ! group || ! version || ! kind ) {
27- return undefined ;
27+ const builtinResource = autoDetectBuiltinResource ( gvk , kubernetesSchema ) ;
28+ if ( builtinResource ) {
29+ return builtinResource ;
2830 }
31+ const customResource = autoDetectCustomResource ( gvk , crdCatalogURI ) ;
32+ if ( customResource ) {
33+ return customResource ;
34+ }
35+ return undefined ;
36+ }
2937
38+ function autoDetectBuiltinResource ( gvk : GroupVersionKind , kubernetesSchema : ResolvedSchema ) : string | undefined {
39+ const { group, version, kind } = gvk ;
40+
41+ const groupWithoutK8sIO = group . replace ( '.k8s.io' , '' ) . replace ( 'rbac.authorization' , 'rbac' ) ;
42+ const k8sTypeName = `io.k8s.api.${ groupWithoutK8sIO . toLowerCase ( ) } .${ version . toLowerCase ( ) } .${ kind . toLowerCase ( ) } ` ;
3043 const k8sSchema : JSONSchema = kubernetesSchema . schema ;
31- const kubernetesBuildIns : string [ ] = ( k8sSchema . oneOf || [ ] )
44+ const matchingBuiltin : string | undefined = ( k8sSchema . oneOf || [ ] )
3245 . map ( ( s ) => {
3346 if ( typeof s === 'boolean' ) {
3447 return undefined ;
3548 }
3649 return s . _$ref || s . $ref ;
3750 } )
38- . filter ( ( ref ) => ref )
39- . map ( ( ref ) => ref . replace ( '_definitions.json#/definitions/' , '' ) . toLowerCase ( ) ) ;
40- const groupWithoutK8sIO = group . replace ( '.k8s.io' , '' ) . replace ( 'rbac.authorization' , 'rbac' ) ;
41- const k8sTypeName = `io.k8s.api.${ groupWithoutK8sIO . toLowerCase ( ) } .${ version . toLowerCase ( ) } .${ kind . toLowerCase ( ) } ` ;
51+ . find ( ( ref ) => {
52+ if ( ! ref ) {
53+ return false ;
54+ }
55+ const lowercaseRef = ref . replace ( '_definitions.json#/definitions/' , '' ) . toLowerCase ( ) ;
56+ return lowercaseRef === k8sTypeName ;
57+ } ) ;
4258
43- if ( kubernetesBuildIns . includes ( k8sTypeName ) ) {
44- return undefined ;
59+ if ( matchingBuiltin ) {
60+ return BASE_KUBERNETES_SCHEMA_URL + matchingBuiltin ;
4561 }
4662
63+ return undefined ;
64+ }
65+
66+ /**
67+ * Retrieve schema by auto-detecting the Kubernetes GroupVersionKind (GVK) from the document.
68+ * If there is no definition for the GVK in the main kubernetes schema,
69+ * the schema is then retrieved from the CRD catalog.
70+ * Public for testing purpose, not part of the API.
71+ * @param doc
72+ * @param crdCatalogURI The URL of the CRD catalog to retrieve the schema from
73+ */
74+ export function autoDetectCustomResource ( gvk : GroupVersionKind , crdCatalogURI : string ) : string | undefined {
75+ const { group, version, kind } = gvk ;
76+
77+ const groupWithoutK8sIO = group . replace ( '.k8s.io' , '' ) . replace ( 'rbac.authorization' , 'rbac' ) ;
78+ const k8sTypeName = `io.k8s.api.${ groupWithoutK8sIO . toLowerCase ( ) } .${ version . toLowerCase ( ) } .${ kind . toLowerCase ( ) } ` ;
79+
4780 if ( k8sTypeName . includes ( 'openshift.io' ) ) {
4881 return `${ crdCatalogURI } /openshift/v4.15-strict/${ kind . toLowerCase ( ) } _${ group . toLowerCase ( ) } _${ version . toLowerCase ( ) } .json` ;
4982 }
@@ -52,14 +85,18 @@ export function autoDetectKubernetesSchemaFromDocument(
5285 return schemaURL ;
5386}
5487
88+ type GroupVersionKind = {
89+ group : string ;
90+ version : string ;
91+ kind : string ;
92+ } ;
93+
5594/**
5695 * Retrieve the group, version and kind from the document.
5796 * Public for testing purpose, not part of the API.
5897 * @param doc
5998 */
60- export function getGroupVersionKindFromDocument (
61- doc : SingleYAMLDocument | JSONDocument
62- ) : { group : string ; version : string ; kind : string } | undefined {
99+ export function getGroupVersionKindFromDocument ( doc : SingleYAMLDocument | JSONDocument ) : GroupVersionKind | undefined {
63100 if ( doc instanceof SingleYAMLDocument ) {
64101 try {
65102 const rootJSON = doc . root . internalNode . toJSON ( ) ;
0 commit comments