mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Switch UserStore to injectable migrations
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
1aa3e46262
commit
3958e613ec
11
src/common/user-store/migrations-token.ts
Normal file
11
src/common/user-store/migrations-token.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||||
|
import type { MigrationDeclaration } from "../base-store/migrations.injectable";
|
||||||
|
|
||||||
|
export const userStoreMigrationInjectionToken = getInjectionToken<MigrationDeclaration>({
|
||||||
|
id: "user-store-migration-token",
|
||||||
|
});
|
||||||
@ -10,6 +10,8 @@ import directoryForUserDataInjectable from "../app-paths/directory-for-user-data
|
|||||||
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
||||||
import loggerInjectable from "../logger.injectable";
|
import loggerInjectable from "../logger.injectable";
|
||||||
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
|
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
|
||||||
|
import storeMigrationsInjectable from "../base-store/migrations.injectable";
|
||||||
|
import { userStoreMigrationInjectionToken } from "./migrations-token";
|
||||||
|
|
||||||
const userStoreInjectable = getInjectable({
|
const userStoreInjectable = getInjectable({
|
||||||
id: "user-store",
|
id: "user-store",
|
||||||
@ -21,6 +23,7 @@ const userStoreInjectable = getInjectable({
|
|||||||
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
|
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
|
||||||
logger: di.inject(loggerInjectable),
|
logger: di.inject(loggerInjectable),
|
||||||
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
|
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
|
||||||
|
migrations: di.inject(storeMigrationsInjectable, userStoreMigrationInjectionToken),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import { app } from "electron";
|
|||||||
import { action, observable, reaction, makeObservable, isObservableArray, isObservableSet, isObservableMap } from "mobx";
|
import { action, observable, reaction, makeObservable, isObservableArray, isObservableSet, isObservableMap } from "mobx";
|
||||||
import type { BaseStoreDependencies } from "../base-store/base-store";
|
import type { BaseStoreDependencies } from "../base-store/base-store";
|
||||||
import { BaseStore } from "../base-store/base-store";
|
import { BaseStore } from "../base-store/base-store";
|
||||||
import migrations from "../../migrations/user-store";
|
|
||||||
import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils";
|
import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils";
|
||||||
import { DESCRIPTORS } from "./preferences-helpers";
|
import { DESCRIPTORS } from "./preferences-helpers";
|
||||||
import type { UserPreferencesModel, StoreType } from "./preferences-helpers";
|
import type { UserPreferencesModel, StoreType } from "./preferences-helpers";
|
||||||
@ -18,7 +17,6 @@ import type { SelectedUpdateChannel } from "../../features/application-update/co
|
|||||||
import type { ReleaseChannel } from "../../features/application-update/common/update-channels";
|
import type { ReleaseChannel } from "../../features/application-update/common/update-channels";
|
||||||
|
|
||||||
export interface UserStoreModel {
|
export interface UserStoreModel {
|
||||||
lastSeenAppVersion: string;
|
|
||||||
preferences: UserPreferencesModel;
|
preferences: UserPreferencesModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,14 +31,11 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
|||||||
constructor(protected readonly dependencies: Dependencies) {
|
constructor(protected readonly dependencies: Dependencies) {
|
||||||
super(dependencies, {
|
super(dependencies, {
|
||||||
configName: "lens-user-store",
|
configName: "lens-user-store",
|
||||||
migrations,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable lastSeenAppVersion = "0.0.0";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated No longer used
|
* @deprecated No longer used
|
||||||
*/
|
*/
|
||||||
@ -137,12 +132,8 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
protected fromStore({ lastSeenAppVersion, preferences }: Partial<UserStoreModel> = {}) {
|
protected fromStore({ preferences }: Partial<UserStoreModel> = {}) {
|
||||||
this.dependencies.logger.debug("UserStore.fromStore()", { lastSeenAppVersion, preferences });
|
this.dependencies.logger.debug("UserStore.fromStore()", { preferences });
|
||||||
|
|
||||||
if (lastSeenAppVersion) {
|
|
||||||
this.lastSeenAppVersion = lastSeenAppVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [key, { fromStore }] of object.entries(DESCRIPTORS)) {
|
for (const [key, { fromStore }] of object.entries(DESCRIPTORS)) {
|
||||||
const curVal = this[key];
|
const curVal = this[key];
|
||||||
@ -170,11 +161,8 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
|||||||
) as UserPreferencesModel;
|
) as UserPreferencesModel;
|
||||||
|
|
||||||
return toJS({
|
return toJS({
|
||||||
lastSeenAppVersion: this.lastSeenAppVersion,
|
|
||||||
|
|
||||||
preferences: {
|
preferences: {
|
||||||
...preferences,
|
...preferences,
|
||||||
|
|
||||||
updateChannel: this.dependencies.selectedUpdateChannel.value.get().id,
|
updateChannel: this.dependencies.selectedUpdateChannel.value.get().id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
36
src/main/user-store/migrations/5.0.0-alpha.3.injectable.ts
Normal file
36
src/main/user-store/migrations/5.0.0-alpha.3.injectable.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Switch representation of hiddenTableColumns in store
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { userStoreMigrationInjectionToken } from "../../../common/user-store/migrations-token";
|
||||||
|
|
||||||
|
interface PreV500Alpha3UserPreferencesModel {
|
||||||
|
hiddenTableColumns?: Record<string, string[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const v500Alpha3UserStoreMigrationInjectable = getInjectable({
|
||||||
|
id: "v5.0.0-alpha.3-user-store-migration",
|
||||||
|
instantiate: () => ({
|
||||||
|
version: "5.0.0-alpha.3",
|
||||||
|
run(store) {
|
||||||
|
const preferences = (store.get("preferences") ?? {}) as PreV500Alpha3UserPreferencesModel;
|
||||||
|
const oldHiddenTableColumns = preferences.hiddenTableColumns;
|
||||||
|
|
||||||
|
if (!oldHiddenTableColumns) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.set("preferences", {
|
||||||
|
...preferences,
|
||||||
|
hiddenTableColumns: Object.entries(oldHiddenTableColumns),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
injectionToken: userStoreMigrationInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default v500Alpha3UserStoreMigrationInjectable;
|
||||||
|
|
||||||
91
src/main/user-store/migrations/5.0.3-beta.1.injectable.ts
Normal file
91
src/main/user-store/migrations/5.0.3-beta.1.injectable.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ClusterStoreModel } from "../../../common/cluster-store/cluster-store";
|
||||||
|
import type { KubeconfigSyncEntry, UserPreferencesModel } from "../../../common/user-store";
|
||||||
|
import { isErrnoException } from "../../../common/utils";
|
||||||
|
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
|
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||||
|
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
|
||||||
|
import isLogicalChildPathInjectable from "../../../common/path/is-logical-child-path.injectable";
|
||||||
|
import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable";
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { userStoreMigrationInjectionToken } from "../../../common/user-store/migrations-token";
|
||||||
|
import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable";
|
||||||
|
import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable";
|
||||||
|
import fsInjectable from "../../../common/fs/fs.injectable";
|
||||||
|
import loggerInjectable from "../../../common/logger.injectable";
|
||||||
|
|
||||||
|
const v503Beta1UserStoreMigrationInjectable = getInjectable({
|
||||||
|
id: "v5.0.3-beta.1-user-store-migration",
|
||||||
|
instantiate: (di) => {
|
||||||
|
const userDataPath = di.inject(directoryForUserDataInjectable);
|
||||||
|
const kubeConfigsPath = di.inject(directoryForKubeConfigsInjectable);
|
||||||
|
const joinPaths = di.inject(joinPathsInjectable);
|
||||||
|
const logger = di.inject(loggerInjectable);
|
||||||
|
const isLogicalChildPath = di.inject(isLogicalChildPathInjectable);
|
||||||
|
const getDirnameOfPath = di.inject(getDirnameOfPathInjectable);
|
||||||
|
const readJsonSync = di.inject(readJsonSyncInjectable);
|
||||||
|
const homeDirectoryPath = di.inject(homeDirectoryPathInjectable);
|
||||||
|
const { existsSync } = di.inject(fsInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: "5.0.3-beta.1",
|
||||||
|
run(store) {
|
||||||
|
try {
|
||||||
|
const { syncKubeconfigEntries = [], ...preferences } = (store.get("preferences") ?? {}) as UserPreferencesModel;
|
||||||
|
const { clusters = [] }: ClusterStoreModel = readJsonSync(joinPaths(userDataPath, "lens-cluster-store.json"), "utf-8") ?? {};
|
||||||
|
const extensionDataDir = joinPaths(userDataPath, "extension_data");
|
||||||
|
const syncPaths = new Set(syncKubeconfigEntries.map(s => s.filePath));
|
||||||
|
|
||||||
|
syncPaths.add(joinPaths(homeDirectoryPath, ".kube"));
|
||||||
|
|
||||||
|
for (const cluster of clusters) {
|
||||||
|
if (!cluster.kubeConfigPath) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const dirOfKubeconfig = getDirnameOfPath(cluster.kubeConfigPath);
|
||||||
|
|
||||||
|
if (dirOfKubeconfig === kubeConfigsPath) {
|
||||||
|
logger.info(`Skipping ${cluster.id} because kubeConfigPath is under the stored KubeConfig folder`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncPaths.has(cluster.kubeConfigPath) || syncPaths.has(dirOfKubeconfig)) {
|
||||||
|
logger.info(`Skipping ${cluster.id} because kubeConfigPath is already being synced`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLogicalChildPath(extensionDataDir, cluster.kubeConfigPath)) {
|
||||||
|
logger.info(`Skipping ${cluster.id} because kubeConfigPath is placed under an extension_data folder`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existsSync(cluster.kubeConfigPath)) {
|
||||||
|
logger.info(`Skipping ${cluster.id} because kubeConfigPath no longer exists`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(`Adding ${cluster.kubeConfigPath} from ${cluster.id} to sync paths`);
|
||||||
|
syncPaths.add(cluster.kubeConfigPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedSyncEntries: KubeconfigSyncEntry[] = [...syncPaths].map(filePath => ({ filePath }));
|
||||||
|
|
||||||
|
logger.info("Final list of synced paths", updatedSyncEntries);
|
||||||
|
store.set("preferences", { ...preferences, syncKubeconfigEntries: updatedSyncEntries });
|
||||||
|
} catch (error) {
|
||||||
|
if (isErrnoException(error) && error.code !== "ENOENT") {
|
||||||
|
// ignore files being missing
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
injectionToken: userStoreMigrationInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default v503Beta1UserStoreMigrationInjectable;
|
||||||
@ -1,14 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Add / reset "lastSeenAppVersion"
|
|
||||||
import type { MigrationDeclaration } from "../helpers";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
version: "2.1.0-beta.4",
|
|
||||||
run(store) {
|
|
||||||
store.set("lastSeenAppVersion", "0.0.0");
|
|
||||||
},
|
|
||||||
} as MigrationDeclaration;
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Switch representation of hiddenTableColumns in store
|
|
||||||
import type { MigrationDeclaration } from "../helpers";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
version: "5.0.0-alpha.3",
|
|
||||||
run(store) {
|
|
||||||
const preferences = store.get("preferences");
|
|
||||||
const oldHiddenTableColumns: Record<string, string[]> = preferences?.hiddenTableColumns;
|
|
||||||
|
|
||||||
if (!oldHiddenTableColumns) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
preferences.hiddenTableColumns = Object.entries(oldHiddenTableColumns);
|
|
||||||
|
|
||||||
store.set("preferences", preferences);
|
|
||||||
},
|
|
||||||
} as MigrationDeclaration;
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { existsSync, readFileSync } from "fs";
|
|
||||||
import os from "os";
|
|
||||||
import type { ClusterStoreModel } from "../../common/cluster-store/cluster-store";
|
|
||||||
import type { KubeconfigSyncEntry, UserPreferencesModel } from "../../common/user-store";
|
|
||||||
import type { MigrationDeclaration } from "../helpers";
|
|
||||||
import { migrationLog } from "../helpers";
|
|
||||||
import { isErrnoException } from "../../common/utils";
|
|
||||||
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
|
||||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
|
||||||
import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
|
||||||
import joinPathsInjectable from "../../common/path/join-paths.injectable";
|
|
||||||
import isLogicalChildPathInjectable from "../../common/path/is-logical-child-path.injectable";
|
|
||||||
import getDirnameOfPathInjectable from "../../common/path/get-dirname.injectable";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
version: "5.0.3-beta.1",
|
|
||||||
run(store) {
|
|
||||||
try {
|
|
||||||
const { syncKubeconfigEntries = [], ...preferences }: UserPreferencesModel = store.get("preferences") ?? {};
|
|
||||||
|
|
||||||
const di = getLegacyGlobalDiForExtensionApi();
|
|
||||||
|
|
||||||
const userDataPath = di.inject(directoryForUserDataInjectable);
|
|
||||||
const kubeConfigsPath = di.inject(directoryForKubeConfigsInjectable);
|
|
||||||
const joinPaths = di.inject(joinPathsInjectable);
|
|
||||||
const isLogicalChildPath = di.inject(isLogicalChildPathInjectable);
|
|
||||||
const getDirnameOfPath = di.inject(getDirnameOfPathInjectable);
|
|
||||||
|
|
||||||
const { clusters = [] }: ClusterStoreModel = JSON.parse(readFileSync(joinPaths(userDataPath, "lens-cluster-store.json"), "utf-8")) ?? {};
|
|
||||||
const extensionDataDir = joinPaths(userDataPath, "extension_data");
|
|
||||||
const syncPaths = new Set(syncKubeconfigEntries.map(s => s.filePath));
|
|
||||||
|
|
||||||
syncPaths.add(joinPaths(os.homedir(), ".kube"));
|
|
||||||
|
|
||||||
for (const cluster of clusters) {
|
|
||||||
if (!cluster.kubeConfigPath) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const dirOfKubeconfig = getDirnameOfPath(cluster.kubeConfigPath);
|
|
||||||
|
|
||||||
if (dirOfKubeconfig === kubeConfigsPath) {
|
|
||||||
migrationLog(`Skipping ${cluster.id} because kubeConfigPath is under the stored KubeConfig folder`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncPaths.has(cluster.kubeConfigPath) || syncPaths.has(dirOfKubeconfig)) {
|
|
||||||
migrationLog(`Skipping ${cluster.id} because kubeConfigPath is already being synced`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLogicalChildPath(extensionDataDir, cluster.kubeConfigPath)) {
|
|
||||||
migrationLog(`Skipping ${cluster.id} because kubeConfigPath is placed under an extension_data folder`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!existsSync(cluster.kubeConfigPath)) {
|
|
||||||
migrationLog(`Skipping ${cluster.id} because kubeConfigPath no longer exists`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
migrationLog(`Adding ${cluster.kubeConfigPath} from ${cluster.id} to sync paths`);
|
|
||||||
syncPaths.add(cluster.kubeConfigPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedSyncEntries: KubeconfigSyncEntry[] = [...syncPaths].map(filePath => ({ filePath }));
|
|
||||||
|
|
||||||
migrationLog("Final list of synced paths", updatedSyncEntries);
|
|
||||||
store.set("preferences", { ...preferences, syncKubeconfigEntries: updatedSyncEntries });
|
|
||||||
} catch (error) {
|
|
||||||
if (isErrnoException(error) && error.code !== "ENOENT") {
|
|
||||||
// ignore files being missing
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
} as MigrationDeclaration;
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// User store migrations
|
|
||||||
|
|
||||||
import { joinMigrations } from "../helpers";
|
|
||||||
|
|
||||||
import version210Beta4 from "./2.1.0-beta.4";
|
|
||||||
import version500Alpha3 from "./5.0.0-alpha.3";
|
|
||||||
import version503Beta1 from "./5.0.3-beta.1";
|
|
||||||
|
|
||||||
export default joinMigrations(
|
|
||||||
version210Beta4,
|
|
||||||
version500Alpha3,
|
|
||||||
version503Beta1,
|
|
||||||
);
|
|
||||||
Loading…
Reference in New Issue
Block a user