1010
1111import * as k8s from '@kubernetes/client-node' ;
1212import * as fs from './fs-extra.js' ;
13+ import { ProductJSON } from './product-json.js' ;
14+ import { mergeFirstWithSecond , parseJSON } from './json-utils.js' ;
1315
1416const CONFIGMAP_NAME = 'vscode-editor-configurations' ;
1517const REMOTE_SETTINGS_PATH = '/checode/remote/data/Machine/settings.json' ;
1618
1719const enum EditorConfigs {
1820 Settings = 'settings.json' ,
1921 Extensions = 'extensions.json' ,
22+ Product = 'product.json' ,
2023}
2124
22- export class EditorConfigurations {
23- private coreV1API : k8s . CoreV1Api ;
25+ /**
26+ * See following documentation for details
27+ * https://eclipse.dev/che/docs/stable/administration-guide/editor-configurations-for-microsoft-visual-studio-code/
28+ */
2429
30+ export class EditorConfigurations {
2531 constructor ( private readonly workspaceFilePath ?: string ) { }
2632
2733 async configure ( ) : Promise < void > {
28- console . log ( '# Checking if editor configurations are provided...' ) ;
34+ console . log ( `# Checking for editor configurations provided by '${ CONFIGMAP_NAME } ' Config Map...` ) ;
35+
36+ if ( ! process . env . DEVWORKSPACE_NAMESPACE ) {
37+ console . log ( ' > process.env.DEVWORKSPACE_NAMESPACE is not set, skip this step' ) ;
38+ return ;
39+ }
2940
3041 try {
3142 const configmap = await this . getConfigmap ( ) ;
3243 if ( ! configmap || ! configmap . data ) {
33- console . log ( ' > Editor configurations are not provided' ) ;
44+ console . log ( ` > Config Map ${ CONFIGMAP_NAME } is not provided, skip this step` ) ;
3445 return ;
3546 }
3647
37- const settingsPromise = this . configureSettings ( configmap ) ;
38- const extensionsPromise = this . configureExtensions ( configmap ) ;
39-
40- await Promise . all ( [ settingsPromise , extensionsPromise ] ) ;
48+ await this . configureSettings ( configmap ) ;
49+ await this . configureExtensions ( configmap ) ;
50+ await this . configureProductJSON ( configmap ) ;
4151 } catch ( error ) {
4252 console . log ( ` > Failed to apply editor configurations ${ error } ` ) ;
4353 }
@@ -46,134 +56,120 @@ export class EditorConfigurations {
4656 private async configureSettings ( configmap : k8s . V1ConfigMap ) : Promise < void > {
4757 const configmapContent = configmap . data ! [ EditorConfigs . Settings ] ;
4858 if ( ! configmapContent ) {
49- console . log ( ` > ${ EditorConfigs . Settings } is not provided in the ${ CONFIGMAP_NAME } configmap` ) ;
50- return ;
51- } else {
52- console . log (
53- ` > ${ EditorConfigs . Settings } is provided in the ${ CONFIGMAP_NAME } configmap, trying to apply it...`
54- ) ;
55- }
56-
57- const settingsFromConfigmap = parseJsonFrom ( configmapContent ) ;
58- if ( ! settingsFromConfigmap ) {
59- console . log (
60- ` > Can not apply editor configurations: failed to parse ${ EditorConfigs . Settings } data from the ${ CONFIGMAP_NAME } configmap`
61- ) ;
6259 return ;
6360 }
6461
65- let remoteSettingsJson ;
66- if ( await fs . fileExists ( REMOTE_SETTINGS_PATH ) ) {
67- console . log ( ` > File with settings is found: ${ REMOTE_SETTINGS_PATH } ` ) ;
62+ console . log ( ' > Configure editor settings...' ) ;
6863
69- const remoteSettingsContent = await fs . readFile ( REMOTE_SETTINGS_PATH ) ;
70- remoteSettingsJson = parseJsonFrom ( remoteSettingsContent ) ;
71- } else {
72- console . log ( ` > File with settings is not found, creating a new one: ${ REMOTE_SETTINGS_PATH } ` ) ;
73- remoteSettingsJson = { } ;
74- }
64+ try {
65+ const settingsFromConfigmap = parseJSON ( configmapContent , {
66+ errorMessage : 'Configmap content is not valid.' ,
67+ } ) ;
68+
69+ let remoteSettingsJson ;
70+ if ( await fs . fileExists ( REMOTE_SETTINGS_PATH ) ) {
71+ console . log ( ` > Found setings file: ${ REMOTE_SETTINGS_PATH } ` ) ;
72+ const remoteSettingsContent = await fs . readFile ( REMOTE_SETTINGS_PATH ) ;
73+ remoteSettingsJson = parseJSON ( remoteSettingsContent , {
74+ errorMessage : 'Settings.json file is not valid.' ,
75+ } ) ;
76+ } else {
77+ console . log ( ` > Creating settings file: ${ REMOTE_SETTINGS_PATH } ` ) ;
78+ remoteSettingsJson = { } ;
79+ }
7580
76- const mergedSettings = { ...remoteSettingsJson , ...settingsFromConfigmap } ;
77- const json = JSON . stringify ( mergedSettings , null , '\t' ) ;
78- await fs . writeFile ( REMOTE_SETTINGS_PATH , json ) ;
81+ const mergedSettings = { ...remoteSettingsJson , ...settingsFromConfigmap } ;
82+ const json = JSON . stringify ( mergedSettings , null , '\t' ) ;
83+ await fs . writeFile ( REMOTE_SETTINGS_PATH , json ) ;
7984
80- console . log ( ` > ${ EditorConfigs . Settings } configs were applied successfully!` ) ;
85+ console . log ( ' > Editor settings have been configured.' ) ;
86+ } catch ( error ) {
87+ console . log ( 'Failed to configure editor settings.' , error ) ;
88+ }
8189 }
8290
8391 private async configureExtensions ( configmap : k8s . V1ConfigMap ) : Promise < void > {
8492 const configmapContent = configmap . data ! [ EditorConfigs . Extensions ] ;
8593 if ( ! configmapContent ) {
86- console . log ( ` > ${ EditorConfigs . Extensions } is not provided in the ${ CONFIGMAP_NAME } configmap` ) ;
8794 return ;
88- } else {
89- console . log (
90- ` > ${ EditorConfigs . Extensions } is provided in the ${ CONFIGMAP_NAME } configmap, trying to apply it...`
91- ) ;
9295 }
9396
94- const extensionsFromConfigmap = parseJsonFrom ( configmapContent ) ;
95- if ( ! extensionsFromConfigmap ) {
96- console . log (
97- ` > Can not apply editor configurations: failed to parse ${ EditorConfigs . Extensions } data from the ${ CONFIGMAP_NAME } configmap`
98- ) ;
99- return ;
100- }
97+ console . log ( ' > Configure workspace extensions...' ) ;
10198
102- if ( this . workspaceFilePath && ( await fs . fileExists ( this . workspaceFilePath ) ) ) {
103- console . log ( ` > File with configs is found: ${ this . workspaceFilePath } ` ) ;
99+ try {
100+ const extensionsFromConfigmap = parseJSON ( configmapContent , {
101+ errorMessage : 'Configmap content is not valid.' ,
102+ } ) ;
104103
105- const workspaceFileContent = await fs . readFile ( this . workspaceFilePath ) ;
106- const workspaceConfigData = parseJsonFrom ( workspaceFileContent ) ;
107- if ( ! workspaceConfigData ) {
108- console . log (
109- ` > Can not apply configurations for ${ EditorConfigs . Extensions } : failed to parse data from the ${ this . workspaceFilePath } `
110- ) ;
104+ if ( ! this . workspaceFilePath ) {
105+ console . log ( ' > Missing workspace file. Skip this step.' ) ;
111106 return ;
112107 }
113108
114- const extensionsSection = 'extensions' ;
115- if ( ! workspaceConfigData [ extensionsSection ] ) {
116- console . log ( ' > Extensions section is absent in the workspace file, creating a new one...' ) ;
117- workspaceConfigData [ extensionsSection ] = { } ;
109+ if ( ! ( await fs . fileExists ( this . workspaceFilePath ) ) ) {
110+ console . log ( ` > Unable to find workspace file: ${ this . workspaceFilePath } . Skip this step.` ) ;
111+ return ;
118112 }
119113
120- workspaceConfigData [ extensionsSection ] = {
121- ...workspaceConfigData [ extensionsSection ] ,
114+ console . log ( ` > Found workspace file: ${ this . workspaceFilePath } ` ) ;
115+
116+ const workspaceFileContent = await fs . readFile ( this . workspaceFilePath ) ;
117+ const workspaceConfigData = parseJSON ( workspaceFileContent , {
118+ errorMessage : 'Workspace file is not valid.' ,
119+ } ) ;
120+
121+ workspaceConfigData [ 'extensions' ] = {
122+ ...( workspaceConfigData [ 'extensions' ] || { } ) ,
122123 ...extensionsFromConfigmap ,
123124 } ;
124125
125126 const json = JSON . stringify ( workspaceConfigData , null , '\t' ) ;
126127 await fs . writeFile ( this . workspaceFilePath , json ) ;
127- console . log ( ` > ${ EditorConfigs . Extensions } was applied successfully!` ) ;
128- } else {
129- console . log ( ` > Workspace Config File with is not found: ${ this . workspaceFilePath } ` ) ;
130- // it's not possible to store extensions for the Remote scope,
131- // for sinle root mode extensions should come with a project, like: /project/.vscode/extensions.json - Folder scope
132- // so, we don't store extensions configs in another place if there is no workspace config file
133- //
128+ console . log ( ' > Workspace extensions have been configured.' ) ;
129+ } catch ( error ) {
130+ console . log ( 'Failed to configure workspace extensions.' , error ) ;
131+ }
132+ }
133+
134+ private async configureProductJSON ( configmap : k8s . V1ConfigMap ) : Promise < void > {
135+ const configmapContent = configmap . data ! [ EditorConfigs . Product ] ;
136+ if ( ! configmapContent ) {
134137 return ;
135138 }
139+
140+ console . log ( ' > Configure product.json ...' ) ;
141+
142+ try {
143+ const productFromConfigmap = parseJSON ( configmapContent , {
144+ errorMessage : 'Configmap content is not valid.' ,
145+ } ) ;
146+
147+ const product = new ProductJSON ( ) ;
148+ await product . load ( ) ;
149+
150+ mergeFirstWithSecond ( productFromConfigmap , product . get ( ) ) ;
151+
152+ await product . save ( ) ;
153+
154+ console . log ( ' > product.json have been configured.' ) ;
155+ } catch ( error ) {
156+ console . log ( `Failed to configure ${ EditorConfigs . Product } .` , error ) ;
157+ }
136158 }
137159
138160 private async getConfigmap ( ) : Promise < k8s . V1ConfigMap | undefined > {
139- const coreV1API = this . getCoreApi ( ) ;
140- const namespace = process . env . DEVWORKSPACE_NAMESPACE ;
141- if ( ! namespace ) {
142- console . log (
143- ' > Error: Can not get Configmap with editor configurations - DEVWORKSPACE_NAMESPACE env variable is not defined'
144- ) ;
145- return undefined ;
146- }
161+ const k8sConfig = new k8s . KubeConfig ( ) ;
162+ k8sConfig . loadFromCluster ( ) ;
163+ const coreV1API = k8sConfig . makeApiClient ( k8s . CoreV1Api ) ;
147164
148165 try {
149- const { body } = await coreV1API . readNamespacedConfigMap ( CONFIGMAP_NAME , namespace ) ;
166+ const { body } = await coreV1API . readNamespacedConfigMap ( CONFIGMAP_NAME , process . env . DEVWORKSPACE_NAMESPACE ! ) ;
150167 return body ;
151168 } catch ( error ) {
152169 console . log (
153- `# > Warning: Can not get Configmap with editor configurations: ${ error . message } , status code: ${ error ?. response ?. statusCode } `
170+ ` > Warning: Can not get Configmap with editor configurations: ${ error . message } , status code: ${ error ?. response ?. statusCode } `
154171 ) ;
155172 return undefined ;
156173 }
157174 }
158-
159- getCoreApi ( ) : k8s . CoreV1Api {
160- if ( ! this . coreV1API ) {
161- const k8sConfig = new k8s . KubeConfig ( ) ;
162- k8sConfig . loadFromCluster ( ) ;
163- this . coreV1API = k8sConfig . makeApiClient ( k8s . CoreV1Api ) ;
164- }
165- return this . coreV1API ;
166- }
167- }
168-
169- export function parseJsonFrom ( content : string ) : any {
170- if ( ! content ) {
171- return undefined ;
172- }
173-
174- try {
175- return JSON . parse ( content ) ;
176- } catch ( parseError ) {
177- console . error ( ` > Error parsing JSON: ${ parseError } ` ) ;
178- }
179175}
0 commit comments