import * as _ from 'lodash' ; import * as semver from 'semver' ; import Uri from 'vscode-uri' ; import * as vscode from 'vscode' ; import { yamlLocator , YamlMap } from "./yaml-locator" ; import { VSCODE_YAML_EXTENSION_ID , KUBERNETES_SCHEMA , GROUP_VERSION_KIND_SEPARATOR } from "./yaml-constant" ; import * as util from "./yaml-util" ; import { Kubectl } from '../kubectl' ; import { ActiveValueTracker } from '../components/contextmanager/active-value-tracker' ; import { BackgroundContextCache } from '../components/contextmanager/background-context-cache' ; import { KubernetesClusterSchemaHolder } from './schema-holder' ; import { shouldSkip } from './consideration-filter' ; declare type YamlSchemaContributor = ( schema : string , requestSchema : ( resource : string ) => string | undefined , requestSchemaContent : ( uri : string ) => string ) => void ; let schemas = null ; export async function registerYamlSchemaSupport ( activeContextTracker , kubectl ) { schemas = new BackgroundContextCache ( activeContextTracker , ( ) => KubernetesClusterSchemaHolder . fromActiveCluster ( kubectl ) , KubernetesClusterSchemaHolder . fallback ( ) ) ; const yamlPlugin = await activateYamlExtension ( ) ; if ( ! yamlPlugin || ! yamlPlugin . registerContributor ) { return ; } yamlPlugin . registerContributor ( KUBERNETES_SCHEMA , requestYamlSchemaUriCallback , requestYamlSchemaContentCallback ) ; } function requestYamlSchemaUriCallback ( resource ) { const textEditor = vscode . window . visibleTextEditors . find ( ( editor ) => editor . document . uri . toString ( ) === resource ) ; if ( textEditor ) { if ( shouldSkip ( textEditor . document ) ) { return undefined ; } const yamlDocs = yamlLocator . getYamlDocuments ( textEditor . document ) ; const choices = [ ] ; const activeSchema = schemas && schemas . active ( ) ; if ( ! activeSchema ) { return undefined ; } yamlDocs . forEach ( ( doc ) => { const topLevelMapping = < YamlMap > doc . nodes . find ( ( node ) => node . kind === 'MAPPING' ) ; if ( topLevelMapping ) { const apiVersion = util . getYamlMappingValue ( topLevelMapping , 'apiVersion' ) ; const kind = util . getYamlMappingValue ( topLevelMapping , 'kind' ) ; if ( apiVersion && kind ) { const qualifiedKind = apiVersion + GROUP_VERSION_KIND_SEPARATOR + kind ; if ( activeSchema . lookup ( qualifiedKind ) ) { choices . push ( qualifiedKind ) ; } } } } ) ; return util . makeKubernetesUri ( choices ) ; } return undefined ; } function requestYamlSchemaContentCallback ( uri ) { const parsedUri = Uri . parse ( uri ) ; if ( parsedUri . scheme !== KUBERNETES_SCHEMA ) { return undefined ; } if ( ! parsedUri . path || ! parsedUri . path . startsWith ( '/' ) ) { return undefined ; } if ( ! schemas ) { return undefined ; } const manifestType = parsedUri . path . slice ( 1 ) ; if ( manifestType . includes ( '+' ) ) { const manifestRefList = manifestType . split ( '+' ) . choose ( util . makeRefOnKubernetes ) ; return JSON . stringify ( { schemaSequence : manifestRefList } ) ; } const schema = schemas . active ( ) . lookup ( manifestType ) ; if ( schema ) { return JSON . stringify ( schema ) ; } return undefined ; } async function activateYamlExtension ( ) { const ext = vscode . extensions . getExtension ( VSCODE_YAML_EXTENSION_ID ) ; if ( ! ext ) { vscode . window . showWarningMessage ( 'Please install \'YAML Support by Red Hat\' via the Extensions pane.' ) ; return undefined ; } const yamlPlugin = await ext . activate ( ) ; if ( ! yamlPlugin || ! yamlPlugin . registerContributor ) { vscode . window . showWarningMessage ( 'The installed Red Hat YAML extension doesn\'t support Kubernetes Intellisense. Please upgrade \'YAML Support by Red Hat\' via the Extensions pane.' ) ; return undefined ; } if ( ext . packageJSON . version && ! semver . gte ( ext . packageJSON . version , '0.0.15' ) ) { vscode . window . showWarningMessage ( 'The installed Red Hat YAML extension doesn\'t support multiple schemas. Please upgrade \'YAML Support by Red Hat\' via the Extensions pane.' ) ; } return yamlPlugin ; } export function updateYAMLSchema ( ) { if ( schemas ) { schemas . invalidateActive ( ) ; } }