1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Move ClusterStore to new format

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-01-24 10:04:03 -05:00
parent bd594e12d5
commit d2485d47b9
6 changed files with 65 additions and 73 deletions

View File

@ -212,7 +212,7 @@ describe("cluster-store", () => {
}); });
it("allows getting all of the clusters", async () => { it("allows getting all of the clusters", async () => {
const storedClusters = clusterStore.clustersList; const storedClusters = clusterStore.clustersList.get();
expect(storedClusters.length).toBe(3); expect(storedClusters.length).toBe(3);
expect(storedClusters[0].id).toBe("cluster1"); expect(storedClusters[0].id).toBe("cluster1");
@ -258,7 +258,7 @@ describe("cluster-store", () => {
}); });
it("does not enable clusters with invalid kubeconfig", () => { it("does not enable clusters with invalid kubeconfig", () => {
const storedClusters = clusterStore.clustersList; const storedClusters = clusterStore.clustersList.get();
expect(storedClusters.length).toBe(1); expect(storedClusters.length).toBe(1);
}); });
@ -295,13 +295,13 @@ describe("cluster-store", () => {
}); });
it("migrates to modern format with kubeconfig in a file", async () => { it("migrates to modern format with kubeconfig in a file", async () => {
const configPath = clusterStore.clustersList[0].kubeConfigPath.get(); const configPath = clusterStore.clustersList.get()[0].kubeConfigPath.get();
expect(readFileSync(configPath)).toBe(minimalValidKubeConfig); expect(readFileSync(configPath)).toBe(minimalValidKubeConfig);
}); });
it("migrates to modern format with icon not in file", async () => { it("migrates to modern format with icon not in file", async () => {
expect(clusterStore.clustersList[0].preferences.icon).toMatch(/data:;base64,/); expect(clusterStore.clustersList.get()[0].preferences.icon).toMatch(/data:;base64,/);
}); });
}); });
}); });

View File

@ -6,17 +6,11 @@ import { getInjectable } from "@ogre-tools/injectable";
import { ClusterStore } from "./cluster-store"; import { ClusterStore } from "./cluster-store";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable"; import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable"; import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.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 storeMigrationsInjectable from "../base-store/migrations.injectable";
import { clusterStoreMigrationInjectionToken } from "./migration-token"; import { clusterStoreMigrationInjectionToken } from "./migration-token";
import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel-prefix"; import createBaseStoreInjectable from "../base-store/create-base-store.injectable";
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync";
import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
const clusterStoreInjectable = getInjectable({ const clusterStoreInjectable = getInjectable({
id: "cluster-store", id: "cluster-store",
@ -24,16 +18,10 @@ const clusterStoreInjectable = getInjectable({
instantiate: (di) => new ClusterStore({ instantiate: (di) => new ClusterStore({
readClusterConfigSync: di.inject(readClusterConfigSyncInjectable), readClusterConfigSync: di.inject(readClusterConfigSyncInjectable),
emitAppEvent: di.inject(emitAppEventInjectable), emitAppEvent: di.inject(emitAppEventInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
migrations: di.inject(storeMigrationsInjectable, clusterStoreMigrationInjectionToken), migrations: di.inject(storeMigrationsInjectable, clusterStoreMigrationInjectionToken),
getBasenameOfPath: di.inject(getBasenameOfPathInjectable), createBaseStore: di.inject(createBaseStoreInjectable),
ipcChannelPrefixes: di.inject(baseStoreIpcChannelPrefixesInjectionToken),
persistStateToConfig: di.inject(persistStateToConfigInjectionToken),
enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken),
shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken),
}), }),
}); });

View File

@ -4,46 +4,75 @@
*/ */
import { action, comparer, computed, makeObservable, observable } from "mobx"; import { action, comparer, computed, observable } from "mobx";
import type { BaseStoreDependencies } from "../base-store/base-store"; import type { BaseStore } from "../base-store/base-store";
import { BaseStore } from "../base-store/base-store";
import { Cluster } from "../cluster/cluster"; import { Cluster } from "../cluster/cluster";
import { toJS } from "../utils"; import { toJS } from "../utils";
import type { ClusterModel, ClusterId } from "../cluster-types"; import type { ClusterModel, ClusterId } from "../cluster-types";
import type { ReadClusterConfigSync } from "./read-cluster-config.injectable"; import type { ReadClusterConfigSync } from "./read-cluster-config.injectable";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable"; import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
import type { CreateBaseStore } from "../base-store/create-base-store.injectable";
import type { Migrations } from "conf/dist/source/types";
import type { Logger } from "../logger";
export interface ClusterStoreModel { export interface ClusterStoreModel {
clusters?: ClusterModel[]; clusters?: ClusterModel[];
} }
interface Dependencies extends BaseStoreDependencies { interface Dependencies {
readClusterConfigSync: ReadClusterConfigSync; readClusterConfigSync: ReadClusterConfigSync;
emitAppEvent: EmitAppEvent; emitAppEvent: EmitAppEvent;
createBaseStore: CreateBaseStore;
readonly storeMigrationVersion: string;
readonly migrations: Migrations<Record<string, unknown>>;
readonly logger: Logger;
} }
export class ClusterStore extends BaseStore<ClusterStoreModel> { export class ClusterStore {
readonly clusters = observable.map<ClusterId, Cluster>(); readonly clusters = observable.map<ClusterId, Cluster>();
private readonly store: BaseStore<ClusterStoreModel>;
constructor(protected readonly dependencies: Dependencies) { constructor(protected readonly dependencies: Dependencies) {
super(dependencies, { this.store = this.dependencies.createBaseStore({
configName: "lens-cluster-store", configName: "lens-cluster-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: { syncOptions: {
equals: comparer.structural, equals: comparer.structural,
}, },
projectVersion: this.dependencies.storeMigrationVersion,
migrations: this.dependencies.migrations as unknown as Migrations<ClusterStoreModel>,
fromStore: action(({ clusters = [] }) => {
const currentClusters = new Map(this.clusters);
const newClusters = new Map<ClusterId, Cluster>();
// update new clusters
for (const clusterModel of clusters) {
try {
let cluster = currentClusters.get(clusterModel.id);
if (cluster) {
cluster.updateModel(clusterModel);
} else {
cluster = new Cluster(
clusterModel,
this.dependencies.readClusterConfigSync(clusterModel),
);
}
newClusters.set(clusterModel.id, cluster);
} catch (error) {
this.dependencies.logger.warn(`[CLUSTER-STORE]: Failed to update/create a cluster: ${error}`);
}
}
this.clusters.replace(newClusters);
}),
toJSON: () => toJS({
clusters: this.clustersList.get().map(cluster => cluster.toJSON()),
}),
}); });
makeObservable(this);
} }
@computed get clustersList(): Cluster[] { readonly clustersList = computed(() => [...this.clusters.values()]);
return Array.from(this.clusters.values());
}
@computed get connectedClustersList(): Cluster[] {
return this.clustersList.filter((c) => !c.disconnected);
}
hasClusters() { hasClusters() {
return this.clusters.size > 0; return this.clusters.size > 0;
@ -72,36 +101,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
return cluster; return cluster;
} }
@action load() {
protected fromStore({ clusters = [] }: ClusterStoreModel = {}) { this.store.load();
const currentClusters = new Map(this.clusters);
const newClusters = new Map<ClusterId, Cluster>();
// update new clusters
for (const clusterModel of clusters) {
try {
let cluster = currentClusters.get(clusterModel.id);
if (cluster) {
cluster.updateModel(clusterModel);
} else {
cluster = new Cluster(
clusterModel,
this.dependencies.readClusterConfigSync(clusterModel),
);
}
newClusters.set(clusterModel.id, cluster);
} catch (error) {
this.dependencies.logger.warn(`[CLUSTER-STORE]: Failed to update/create a cluster: ${error}`);
}
}
this.clusters.replace(newClusters);
}
toJSON(): ClusterStoreModel {
return toJS({
clusters: this.clustersList.map(cluster => cluster.toJSON()),
});
} }
} }

View File

@ -12,7 +12,7 @@ const handleInitialClusterStateSyncInjectable = getRequestChannelListenerInjecta
getHandler: (di) => { getHandler: (di) => {
const clusterStore = di.inject(clusterStoreInjectable); const clusterStore = di.inject(clusterStoreInjectable);
return () => clusterStore.clustersList.map(cluster => ({ return () => clusterStore.clustersList.get().map(cluster => ({
clusterId: cluster.id, clusterId: cluster.id,
state: cluster.getState(), state: cluster.getState(),
})); }));

View File

@ -42,15 +42,15 @@ export class ClusterManager {
init = once(() => { init = once(() => {
// reacting to every cluster's state change and total amount of items // reacting to every cluster's state change and total amount of items
reaction( reaction(
() => this.dependencies.store.clustersList.map(c => c.getState()), () => this.dependencies.store.clustersList.get().map(c => c.getState()),
() => this.updateCatalog(this.dependencies.store.clustersList), () => this.updateCatalog(this.dependencies.store.clustersList.get()),
{ fireImmediately: false }, { fireImmediately: false },
); );
// reacting to every cluster's preferences change and total amount of items // reacting to every cluster's preferences change and total amount of items
reaction( reaction(
() => this.dependencies.store.clustersList.map(c => toJS(c.preferences)), () => this.dependencies.store.clustersList.get().map(c => toJS(c.preferences)),
() => this.updateCatalog(this.dependencies.store.clustersList), () => this.updateCatalog(this.dependencies.store.clustersList.get()),
{ fireImmediately: false }, { fireImmediately: false },
); );
@ -208,7 +208,9 @@ export class ClusterManager {
this.dependencies.logger.info(`${logPrefix} network is offline`); this.dependencies.logger.info(`${logPrefix} network is offline`);
await Promise.allSettled( await Promise.allSettled(
this.dependencies.store.clustersList this.dependencies.store
.clustersList
.get()
.filter(cluster => !cluster.disconnected.get()) .filter(cluster => !cluster.disconnected.get())
.map(async (cluster) => { .map(async (cluster) => {
cluster.online.set(false); cluster.online.set(false);
@ -225,7 +227,9 @@ export class ClusterManager {
this.dependencies.logger.info(`${logPrefix} network is online`); this.dependencies.logger.info(`${logPrefix} network is online`);
await Promise.allSettled( await Promise.allSettled(
this.dependencies.store.clustersList this.dependencies.store
.clustersList
.get()
.filter(cluster => !cluster.disconnected.get()) .filter(cluster => !cluster.disconnected.get())
.map((cluster) => ( .map((cluster) => (
this.dependencies this.dependencies
@ -236,7 +240,7 @@ export class ClusterManager {
}; };
stop() { stop() {
for (const cluster of this.dependencies.store.clustersList) { for (const cluster of this.dependencies.store.clustersList.get()) {
this.dependencies this.dependencies
.getClusterConnection(cluster) .getClusterConnection(cluster)
.disconnect(); .disconnect();

View File

@ -60,7 +60,7 @@ export const setupIpcMainHandlers = ({
}); });
ipcMainHandle(clusterStates, () => ( ipcMainHandle(clusterStates, () => (
clusterStore.clustersList.map(cluster => ({ clusterStore.clustersList.get().map(cluster => ({
id: cluster.id, id: cluster.id,
state: cluster.getState(), state: cluster.getState(),
})) }))