Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
chore: Store user preferences in a config-map (#1260)
Browse files Browse the repository at this point in the history
Use config-map to store and restore user preferences. This gives an ability not to use che-server API for storing preferences.
  • Loading branch information
vinokurig authored Jan 19, 2022
1 parent af0d0b4 commit 9c6d63b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 7 deletions.
4 changes: 3 additions & 1 deletion extensions/eclipse-che-theia-user-preferences/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"@theia/workspace": "next",
"nsfw": "^2.1.2",
"@theia/preferences": "next",
"@eclipse-che/theia-plugin-ext": "^0.0.1"
"@eclipse-che/theia-plugin-ext": "^0.0.1",
"@kubernetes/client-node": "^0.12.1",
"@eclipse-che/theia-remote-impl-che-server": "0.0.1"
},
"devDependencies": {
"rimraf": "latest",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,36 @@
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import * as k8s from '@kubernetes/client-node';
import * as nsfw from 'nsfw';

import { CheK8SService, WorkspaceService } from '@eclipse-che/theia-remote-api/lib/common';
import { Emitter, Event } from '@theia/core';
import { Preferences, UserService } from '@eclipse-che/theia-remote-api/lib/common/user-service';
import { dirname, resolve } from 'path';
import { ensureDir, readFile, writeFile } from 'fs-extra';
import { inject, injectable } from 'inversify';

import { CheK8SServiceImpl } from '@eclipse-che/theia-remote-impl-che-server/lib/node/che-server-k8s-service-impl';
import { homedir } from 'os';
import { readFileSync } from 'fs';

export const THEIA_PREFERENCES_KEY = 'theia-user-preferences';
export const WORKSPACE_PREFERENCES_CONFIGMAP_NAME = 'workspace-preferences-configmap';
export const THEIA_USER_PREFERENCES_PATH = resolve(homedir(), '.theia', 'settings.json');
const INFRASTRUCTURE_NAMESPACE = 'infrastructureNamespace';

@injectable()
export class CheTheiaUserPreferencesSynchronizer {
@inject(UserService)
protected userService: UserService;

@inject(CheK8SService)
private readonly cheK8SService: CheK8SServiceImpl;

@inject(WorkspaceService)
private readonly workspaceService: WorkspaceService;

protected settingsJsonWatcher: nsfw.NSFW | undefined;

protected readonly onUserPreferencesModifyEmitter = new Emitter<object>();
Expand All @@ -39,11 +51,30 @@ export class CheTheiaUserPreferencesSynchronizer {
* Provides stored Theia user preferences into workspace.
*/
public async readTheiaUserPreferencesFromCheSettings(): Promise<void> {
const chePreferences = await this.userService.getUserPreferences(THEIA_PREFERENCES_KEY);
const theiaPreferences = chePreferences[THEIA_PREFERENCES_KEY] ? chePreferences[THEIA_PREFERENCES_KEY] : '{}';
const theiaPreferencesBeautified = JSON.stringify(JSON.parse(theiaPreferences), undefined, 3);
await ensureDir(dirname(THEIA_USER_PREFERENCES_PATH));
await writeFile(THEIA_USER_PREFERENCES_PATH, theiaPreferencesBeautified, 'utf8');
let content = '';
try {
const request = await this.cheK8SService
.makeApiClient(k8s.CoreV1Api)
.readNamespacedConfigMap(WORKSPACE_PREFERENCES_CONFIGMAP_NAME, await this.getWorkspaceNamespace());
if (request.body && request.body.data && request.body.data[THEIA_PREFERENCES_KEY]) {
content = JSON.stringify(JSON.parse(request.body.data[THEIA_PREFERENCES_KEY]), undefined, 3);
}
} catch (e) {
console.error('Failed to retrieve preferences storage.', e);
}
await writeFile(THEIA_USER_PREFERENCES_PATH, content, 'utf8');
}

private async getWorkspaceNamespace(): Promise<string> {
// devworkspace use-case
const workspaceNamespace = process.env.DEVWORKSPACE_NAMESPACE;
if (workspaceNamespace) {
return Promise.resolve(workspaceNamespace);
}
// grab current workspace
const workspace = await this.workspaceService.currentWorkspace();
return workspace.attributes?.[INFRASTRUCTURE_NAMESPACE] || workspace.namespace || '';
}

public async getPreferences(): Promise<object> {
Expand All @@ -64,10 +95,27 @@ export class CheTheiaUserPreferencesSynchronizer {
return;
}

this.settingsJsonWatcher = await nsfw(THEIA_USER_PREFERENCES_PATH, (events: nsfw.FileChangeEvent[]) => {
this.settingsJsonWatcher = await nsfw(THEIA_USER_PREFERENCES_PATH, async (events: nsfw.FileChangeEvent[]) => {
for (const event of events) {
if (event.action === nsfw.actions.MODIFIED) {
this.updateTheiaUserPreferencesInCheSettings();
const client = this.cheK8SService.makeApiClient(k8s.CoreV1Api);
client.defaultHeaders = {
Accept: 'application/json',
'Content-Type': k8s.PatchUtils.PATCH_FORMAT_STRATEGIC_MERGE_PATCH,
};
const preferences = readFileSync(THEIA_USER_PREFERENCES_PATH).toString();
const theiaPreferencesBeautified = JSON.stringify(JSON.parse(preferences), undefined, 3);
try {
await client.patchNamespacedConfigMap(
WORKSPACE_PREFERENCES_CONFIGMAP_NAME,
await this.getWorkspaceNamespace(),
{
data: { [THEIA_PREFERENCES_KEY]: theiaPreferencesBeautified },
}
);
} catch (e) {
console.error('Failed to update preferences storage.', e);
}
return;
}
}
Expand Down

0 comments on commit 9c6d63b

Please sign in to comment.