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

Fully split apart the clusters storage

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-03-16 15:15:44 -04:00
parent 12e438892d
commit f1f8e198a2
98 changed files with 441 additions and 399 deletions

View File

@ -6,7 +6,6 @@ import type { UserStore } from "../user-store";
import userStoreInjectable from "../user-store/user-store.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import type { ClusterStoreModel } from "../cluster-store/cluster-store";
import { defaultThemeId } from "../vars";
import writeFileInjectable from "../fs/write-file.injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
@ -15,6 +14,7 @@ import releaseChannelInjectable from "../vars/release-channel.injectable";
import defaultUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/default-update-channel.injectable";
import writeJsonSyncInjectable from "../fs/write-json-sync.injectable";
import writeFileSyncInjectable from "../fs/write-file-sync.injectable";
import type { ClusterStoreModel } from "../../features/cluster/storage/common/storage.injectable";
describe("user store tests", () => {
let userStore: UserStore;

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { ClusterStore } from "./cluster-store";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
import loggerInjectable from "../logger.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import persistentStorageMigrationsInjectable from "../persistent-storage/migrations.injectable";
import { clusterStoreMigrationInjectionToken } from "./migration-token";
import createPersistentStorageInjectable from "../persistent-storage/create.injectable";
const clusterStoreInjectable = getInjectable({
id: "cluster-store",
instantiate: (di) => new ClusterStore({
readClusterConfigSync: di.inject(readClusterConfigSyncInjectable),
emitAppEvent: di.inject(emitAppEventInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
migrations: di.inject(persistentStorageMigrationsInjectable, clusterStoreMigrationInjectionToken),
createPersistentStorage: di.inject(createPersistentStorageInjectable),
}),
});
export default clusterStoreInjectable;

View File

@ -1,106 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { action, comparer, computed, observable } from "mobx";
import { Cluster } from "../cluster/cluster";
import { toJS } from "../utils";
import type { ClusterModel, ClusterId } from "../cluster-types";
import type { ReadClusterConfigSync } from "./read-cluster-config.injectable";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
import type { CreatePersistentStorage, PersistentStorage } from "../persistent-storage/create.injectable";
import type { Migrations } from "conf/dist/source/types";
import type { Logger } from "../logger";
export interface ClusterStoreModel {
clusters?: ClusterModel[];
}
interface Dependencies {
readClusterConfigSync: ReadClusterConfigSync;
emitAppEvent: EmitAppEvent;
createPersistentStorage: CreatePersistentStorage;
readonly storeMigrationVersion: string;
readonly migrations: Migrations<Record<string, unknown>>;
readonly logger: Logger;
}
export class ClusterStore {
readonly clusters = observable.map<ClusterId, Cluster>();
private readonly store: PersistentStorage;
constructor(protected readonly dependencies: Dependencies) {
this.store = this.dependencies.createPersistentStorage<ClusterStoreModel>({
configName: "lens-cluster-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: {
equals: comparer.structural,
},
projectVersion: this.dependencies.storeMigrationVersion,
migrations: this.dependencies.migrations,
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()),
}),
});
}
readonly clustersList = computed(() => [...this.clusters.values()]);
hasClusters() {
return this.clusters.size > 0;
}
getById(id: ClusterId | undefined): Cluster | undefined {
if (id) {
return this.clusters.get(id);
}
return undefined;
}
addCluster(clusterOrModel: ClusterModel | Cluster): Cluster {
this.dependencies.emitAppEvent({ name: "cluster", action: "add" });
const cluster = clusterOrModel instanceof Cluster
? clusterOrModel
: new Cluster(
clusterOrModel,
this.dependencies.readClusterConfigSync(clusterOrModel),
);
this.clusters.set(cluster.id, cluster);
return cluster;
}
load() {
this.store.loadAndStartSyncing();
}
}

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const configMapsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const horizontalPodAutoscalersRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const leasesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const limitRangesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const podDisruptionBudgetsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const priorityClassesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const resourceQuotasRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const runtimeClassesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const secretsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const verticalPodAutoscalersRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../front-end-route-injection-token";
const eventsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../front-end-route-injection-token";
const namespacesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const endpointsRouteInjectable = getInjectable({

View File

@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
import {
shouldShowResourceInjectionToken,
} from "../../../../../cluster-store/allowed-resources-injection-token";
} from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
const ingressClassesesRouteInjectable = getInjectable({
id: "ingress-classes-route",

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { computedOr } from "@k8slens/utilities";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const networkPoliciesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const servicesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../front-end-route-injection-token";
const nodesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../front-end-route-injection-token";
const clusterOverviewRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const persistentVolumeClaimsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const persistentVolumesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const storageClassesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const clusterRoleBindingsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const clusterRolesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const podSecurityPoliciesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const roleBindingsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const rolesRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const serviceAccountsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const cronJobsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const daemonsetsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const deploymentsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const jobsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const podsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const replicasetsRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const replicationControllersRouteInjectable = getInjectable({

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const statefulsetsRouteInjectable = getInjectable({

View File

@ -6,22 +6,14 @@ import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting";
import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token";
import { frontEndRouteInjectionToken } from "./front-end-route-injection-token";
import { filter, map } from "lodash/fp";
import clusterStoreInjectable from "../cluster-store/cluster-store.injectable";
import type { ClusterStore } from "../cluster-store/cluster-store";
import { pipeline } from "@ogre-tools/fp";
describe("verify-that-all-routes-have-component", () => {
it("verify that routes have route component", () => {
const rendererDi = getDiForUnitTesting();
rendererDi.override(clusterStoreInjectable, () => ({
getById: () => null,
} as unknown as ClusterStore));
const routes = rendererDi.injectMany(frontEndRouteInjectionToken);
const routeComponents = rendererDi.injectMany(
routeSpecificComponentInjectionToken,
);
const routeComponents = rendererDi.injectMany(routeSpecificComponentInjectionToken);
const routesMissingComponent = pipeline(
routes,

View File

@ -37,7 +37,7 @@ import namespaceApiInjectable from "../../common/k8s-api/endpoints/namespace.api
import kubeEventApiInjectable from "../../common/k8s-api/endpoints/events.api.injectable";
import roleBindingApiInjectable from "../../common/k8s-api/endpoints/role-binding.api.injectable";
import customResourceDefinitionApiInjectable from "../../common/k8s-api/endpoints/custom-resource-definition.api.injectable";
import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import requestMetricsInjectable from "../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";

View File

@ -231,7 +231,7 @@ exports[`opening catalog entity details panel renders 1`] = `
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -1052,7 +1052,7 @@ exports[`opening catalog entity details panel when navigated to the catalog rend
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -1873,7 +1873,7 @@ exports[`opening catalog entity details panel when navigated to the catalog when
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -2726,7 +2726,7 @@ exports[`opening catalog entity details panel when navigated to the catalog when
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -3579,7 +3579,7 @@ exports[`opening catalog entity details panel when navigated to the catalog when
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -4683,7 +4683,7 @@ exports[`opening catalog entity details panel when navigated to the catalog when
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -5524,7 +5524,7 @@ exports[`opening catalog entity details panel when navigated to the catalog when
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -6365,7 +6365,7 @@ exports[`opening catalog entity details panel when navigated to the catalog when
class="HotbarSelector"
>
<i
class="Icon Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -6841,7 +6841,7 @@ exports[`opening catalog entity details panel when not navigated to the catalog
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span

View File

@ -6,19 +6,18 @@
import type { DiContainer } from "@ogre-tools/injectable";
import type { RenderResult } from "@testing-library/react";
import { KubernetesCluster, WebLink } from "../../common/catalog-entities";
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { Cluster } from "../../common/cluster/cluster";
import navigateToCatalogInjectable from "../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable";
import { advanceFakeTime, testUsingFakeTime } from "../../test-utils/use-fake-time";
import { advanceFakeTime } from "../../test-utils/use-fake-time";
import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable";
import showEntityDetailsInjectable from "../../renderer/components/+catalog/entity-details/show.injectable";
import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
import addClusterInjectable from "../cluster/storage/common/add.injectable";
describe("opening catalog entity details panel", () => {
let builder: ApplicationBuilder;
let rendered: RenderResult;
let windowDi: DiContainer;
let cluster: Cluster;
let clusterEntity: KubernetesCluster;
let localClusterEntity: KubernetesCluster;
let otherEntity: WebLink;
@ -26,20 +25,7 @@ describe("opening catalog entity details panel", () => {
beforeEach(async () => {
builder = getApplicationBuilder();
builder.beforeWindowStart(({ windowDi }) => {
// TODO: remove once ClusterStore can be used without overriding it
windowDi.override(getClusterByIdInjectable, () => (clusterId) => {
if (clusterId === cluster?.id) {
return cluster;
}
return undefined;
});
});
testUsingFakeTime();
builder.afterWindowStart(({ windowDi }) => {
builder.afterWindowStart(async ({ windowDi }) => {
clusterEntity = new KubernetesCluster({
metadata: {
labels: {},
@ -82,12 +68,33 @@ describe("opening catalog entity details panel", () => {
phase: "available",
},
});
cluster = new Cluster({
contextName: clusterEntity.spec.kubeconfigContext,
const writeJsonFile = windowDi.inject(writeJsonFileInjectable);
const addCluster = windowDi.inject(addClusterInjectable);
await writeJsonFile(clusterEntity.spec.kubeconfigPath, {
contexts: [{
name: clusterEntity.spec.kubeconfigContext,
context: {
cluster: "some-cluster",
user: "some-user",
},
}],
clusters: [{
name: "some-cluster",
cluster: {
server: "https://localhost:9999",
},
}],
users: [{
name: "some-user",
}],
});
addCluster({
id: clusterEntity.getId(),
kubeConfigPath: clusterEntity.spec.kubeconfigPath,
}, {
clusterServerUrl: "https://localhost:9999",
contextName: clusterEntity.spec.kubeconfigContext,
});
// TODO: replace with proper entity source once syncing entities between main and windows is injectable

View File

@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import clusterConnectionInjectable from "../../../../main/cluster/cluster-connection.injectable";
import getClusterByIdInjectable from "../../storage/common/get-by-id.injectable";
import { requestClusterActivationInjectionToken } from "../common/request-token";
const requestClusterActivationInjectable = getInjectable({

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable";
import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable";
import clusterFramesInjectable from "../../../../common/cluster-frames.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import clusterConnectionInjectable from "../../../../main/cluster/cluster-connection.injectable";
import getClusterByIdInjectable from "../../storage/common/get-by-id.injectable";
import { requestClusterDeactivationInjectionToken } from "../common/request-token";
const requestClusterDeactivationInjectable = getInjectable({

View File

@ -4,7 +4,6 @@
*/
import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable";
import clusterFramesInjectable from "../../../../common/cluster-frames.injectable";
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable";
import removePathInjectable from "../../../../common/fs/remove.injectable";
import joinPathsInjectable from "../../../../common/path/join-paths.injectable";
@ -12,22 +11,23 @@ import clusterConnectionInjectable from "../../../../main/cluster/cluster-connec
import { noop } from "@k8slens/utilities";
import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { deleteClusterChannel } from "../common/delete-channel";
import clustersStateInjectable from "../../storage/common/state.injectable";
const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "delete-cluster-channel-listener",
channel: deleteClusterChannel,
getHandler: (di) => {
const emitAppEvent = di.inject(emitAppEventInjectable);
const clusterStore = di.inject(clusterStoreInjectable);
const clusterFrames = di.inject(clusterFramesInjectable);
const joinPaths = di.inject(joinPathsInjectable);
const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable);
const deleteFile = di.inject(removePathInjectable);
const clustersState = di.inject(clustersStateInjectable);
return async (clusterId) => {
emitAppEvent({ name: "cluster", action: "remove" });
const cluster = clusterStore.getById(clusterId);
const cluster = clustersState.get(clusterId);
if (!cluster) {
return;
@ -37,9 +37,7 @@ const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectab
clusterConnection.disconnect();
clusterFrames.delete(cluster.id);
// Remove from the cluster store as well, this should clear any old settings
clusterStore.clusters.delete(cluster.id);
clustersState.delete(cluster.id);
// remove the local storage file
const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`);

View File

@ -5,7 +5,7 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type { IComputedValue } from "mobx";
import type { KubeApiResourceDescriptor } from "../rbac";
import type { KubeApiResourceDescriptor } from "../../../../common/rbac";
export const shouldShowResourceInjectionToken = getInjectionToken<IComputedValue<boolean>, KubeApiResourceDescriptor>({
id: "should-show-resource",

View File

@ -2,17 +2,17 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import clustersInjectable from "../../storage/common/clusters.injectable";
import { initialClusterStatesChannel } from "../common/channels";
const handleInitialClusterStateSyncInjectable = getRequestChannelListenerInjectable({
id: "handle-initial-cluster-state-sync",
channel: initialClusterStatesChannel,
getHandler: (di) => {
const clusterStore = di.inject(clusterStoreInjectable);
const clusters = di.inject(clustersInjectable);
return () => clusterStore.clustersList.get().map(cluster => ({
return () => clusters.get().map(cluster => ({
clusterId: cluster.id,
state: cluster.getState(),
}));

View File

@ -5,22 +5,22 @@
import { getInjectable } from "@ogre-tools/injectable";
import { isEqual } from "lodash";
import { autorun } from "mobx";
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import type { ClusterId, ClusterState } from "../../../../common/cluster-types";
import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application";
import initClusterStoreInjectable from "../../store/main/init.injectable";
import initClusterStoreInjectable from "../../storage/main/init.injectable";
import emitClusterStateUpdateInjectable from "./emit-update.injectable";
import clustersInjectable from "../../storage/common/clusters.injectable";
const setupClusterStateBroadcastingInjectable = getInjectable({
id: "setup-cluster-state-broadcasting",
instantiate: (di) => ({
run: () => {
const emitClusterStateUpdate = di.inject(emitClusterStateUpdateInjectable);
const clusterStore = di.inject(clusterStoreInjectable);
const clusters = di.inject(clustersInjectable);
const prevStates = new Map<ClusterId, ClusterState>();
autorun(() => {
for (const cluster of clusterStore.clusters.values()) {
for (const cluster of clusters.get()) {
const prevState = prevStates.get(cluster.id);
const curState = cluster.getState();

View File

@ -2,8 +2,8 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import getClusterByIdInjectable from "../../storage/common/get-by-id.injectable";
import { clusterStateSyncChannel } from "../common/channels";
const clusterStateListenerInjectable = getMessageChannelListenerInjectable({

View File

@ -3,9 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
import initClusterStoreInjectable from "../../store/renderer/init.injectable";
import getClusterByIdInjectable from "../../storage/common/get-by-id.injectable";
import initClusterStoreInjectable from "../../storage/renderer/init.injectable";
import requestInitialClusterStatesInjectable from "./request-initial.injectable";
const setupClusterStateSyncInjectable = getInjectable({

View File

@ -3,29 +3,35 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { ClusterStore } from "../cluster-store/cluster-store";
import type { GetCustomKubeConfigFilePath } from "../app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
import getCustomKubeConfigFilePathInjectable from "../app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
import clusterStoreInjectable from "../cluster-store/cluster-store.injectable";
import type { GetCustomKubeConfigFilePath } from "../../../common/app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
import getCustomKubeConfigFilePathInjectable from "../../../common/app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { getDiForUnitTesting } from "../../../main/getDiForUnitTesting";
import assert from "assert";
import directoryForTempInjectable from "../app-paths/directory-for-temp/directory-for-temp.injectable";
import kubectlBinaryNameInjectable from "../../main/kubectl/binary-name.injectable";
import kubectlDownloadingNormalizedArchInjectable from "../../main/kubectl/normalized-arch.injectable";
import normalizedPlatformInjectable from "../vars/normalized-platform.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import type { WriteJsonSync } from "../fs/write-json-sync.injectable";
import writeJsonSyncInjectable from "../fs/write-json-sync.injectable";
import type { ReadFileSync } from "../fs/read-file-sync.injectable";
import readFileSyncInjectable from "../fs/read-file-sync.injectable";
import directoryForTempInjectable from "../../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
import kubectlBinaryNameInjectable from "../../../main/kubectl/binary-name.injectable";
import kubectlDownloadingNormalizedArchInjectable from "../../../main/kubectl/normalized-arch.injectable";
import normalizedPlatformInjectable from "../../../common/vars/normalized-platform.injectable";
import storeMigrationVersionInjectable from "../../../common/vars/store-migration-version.injectable";
import type { WriteJsonSync } from "../../../common/fs/write-json-sync.injectable";
import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable";
import type { ReadFileSync } from "../../../common/fs/read-file-sync.injectable";
import readFileSyncInjectable from "../../../common/fs/read-file-sync.injectable";
import { readFileSync } from "fs";
import type { WriteFileSync } from "../fs/write-file-sync.injectable";
import writeFileSyncInjectable from "../fs/write-file-sync.injectable";
import type { WriteBufferSync } from "../fs/write-buffer-sync.injectable";
import writeBufferSyncInjectable from "../fs/write-buffer-sync.injectable";
import { Cluster } from "../cluster/cluster";
import type { WriteFileSync } from "../../../common/fs/write-file-sync.injectable";
import writeFileSyncInjectable from "../../../common/fs/write-file-sync.injectable";
import type { WriteBufferSync } from "../../../common/fs/write-buffer-sync.injectable";
import writeBufferSyncInjectable from "../../../common/fs/write-buffer-sync.injectable";
import { Cluster } from "../../../common/cluster/cluster";
import clustersPersistentStorageInjectable from "./common/storage.injectable";
import type { PersistentStorage } from "../../../common/persistent-storage/create.injectable";
import type { AddCluster } from "./common/add.injectable";
import addClusterInjectable from "./common/add.injectable";
import type { GetClusterById } from "./common/get-by-id.injectable";
import getClusterByIdInjectable from "./common/get-by-id.injectable";
import type { IComputedValue } from "mobx";
import clustersInjectable from "./common/clusters.injectable";
// NOTE: this is intended to read the actual file system
const testDataIcon = readFileSync("test-data/cluster-store-migration-icon.png");
@ -54,15 +60,18 @@ users:
token: kubeconfig-user-q4lm4:xxxyyyy
`;
describe("cluster-store", () => {
describe("cluster storage technical tests", () => {
let di: DiContainer;
let clusterStore: ClusterStore;
let clustersPersistentStorage: PersistentStorage;
let writeJsonSync: WriteJsonSync;
let writeFileSync: WriteFileSync;
let writeBufferSync: WriteBufferSync;
let readFileSync: ReadFileSync;
let getCustomKubeConfigFilePath: GetCustomKubeConfigFilePath;
let writeFileSyncAndReturnPath: (filePath: string, contents: string) => string;
let addCluster: AddCluster;
let getClusterById: GetClusterById;
let clusters: IComputedValue<Cluster[]>;
beforeEach(async () => {
di = getDiForUnitTesting();
@ -76,6 +85,9 @@ describe("cluster-store", () => {
writeFileSync = di.inject(writeFileSyncInjectable);
writeBufferSync = di.inject(writeBufferSyncInjectable);
readFileSync = di.inject(readFileSyncInjectable);
addCluster = di.inject(addClusterInjectable);
getClusterById = di.inject(getClusterByIdInjectable);
clusters = di.inject(clustersInjectable);
writeFileSyncAndReturnPath = (filePath, contents) => (writeFileSync(filePath, contents), filePath);
});
@ -84,8 +96,8 @@ describe("cluster-store", () => {
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
writeJsonSync("/some-directory-for-user-data/lens-cluster-store.json", {});
clusterStore = di.inject(clusterStoreInjectable);
clusterStore.load();
clustersPersistentStorage = di.inject(clustersPersistentStorageInjectable);
clustersPersistentStorage.loadAndStartSyncing();
});
describe("with foo cluster added", () => {
@ -106,11 +118,11 @@ describe("cluster-store", () => {
clusterServerUrl,
});
clusterStore.addCluster(cluster);
addCluster(cluster);
});
it("adds new cluster to store", async () => {
const storedCluster = clusterStore.getById("foo");
const storedCluster = getClusterById("foo");
assert(storedCluster);
@ -124,9 +136,7 @@ describe("cluster-store", () => {
describe("with prod and dev clusters added", () => {
beforeEach(() => {
const store = clusterStore;
store.addCluster({
addCluster({
id: "prod",
contextName: "foo",
preferences: {
@ -137,7 +147,7 @@ describe("cluster-store", () => {
kubeconfig,
),
});
store.addCluster({
addCluster({
id: "dev",
contextName: "foo2",
preferences: {
@ -151,8 +161,7 @@ describe("cluster-store", () => {
});
it("check if store can contain multiple clusters", () => {
expect(clusterStore.hasClusters()).toBeTruthy();
expect(clusterStore.clusters.size).toBe(2);
expect(clusters.get().length).toBe(2);
});
it("check if cluster's kubeconfig file saved", () => {
@ -199,11 +208,11 @@ describe("cluster-store", () => {
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
clusterStore = di.inject(clusterStoreInjectable);
clusterStore.load();
clustersPersistentStorage = di.inject(clustersPersistentStorageInjectable);
clustersPersistentStorage.loadAndStartSyncing();
});
it("allows to retrieve a cluster", () => {
const storedCluster = clusterStore.getById("cluster1");
const storedCluster = getClusterById("cluster1");
assert(storedCluster);
@ -212,7 +221,7 @@ describe("cluster-store", () => {
});
it("allows getting all of the clusters", async () => {
const storedClusters = clusterStore.clustersList.get();
const storedClusters = clusters.get();
expect(storedClusters.length).toBe(3);
expect(storedClusters[0].id).toBe("cluster1");
@ -253,12 +262,12 @@ describe("cluster-store", () => {
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
clusterStore = di.inject(clusterStoreInjectable);
clusterStore.load();
clustersPersistentStorage = di.inject(clustersPersistentStorageInjectable);
clustersPersistentStorage.loadAndStartSyncing();
});
it("does not enable clusters with invalid kubeconfig", () => {
const storedClusters = clusterStore.clustersList.get();
const storedClusters = clusters.get();
expect(storedClusters.length).toBe(1);
});
@ -290,18 +299,18 @@ describe("cluster-store", () => {
writeBufferSync("/some-directory-for-user-data/icon_path", testDataIcon);
clusterStore = di.inject(clusterStoreInjectable);
clusterStore.load();
clustersPersistentStorage = di.inject(clustersPersistentStorageInjectable);
clustersPersistentStorage.loadAndStartSyncing();
});
it("migrates to modern format with kubeconfig in a file", async () => {
const configPath = clusterStore.clustersList.get()[0].kubeConfigPath.get();
const configPath = clusters.get()[0].kubeConfigPath.get();
expect(readFileSync(configPath)).toBe(minimalValidKubeConfig);
});
it("migrates to modern format with icon not in file", async () => {
expect(clusterStore.clustersList.get()[0].preferences.icon).toMatch(/data:;base64,/);
expect(clusters.get()[0].preferences.icon).toMatch(/data:;base64,/);
});
});
});

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { action } from "mobx";
import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
import type { ClusterModel } from "../../../../common/cluster-types";
import { Cluster } from "../../../../common/cluster/cluster";
import clustersStateInjectable from "./state.injectable";
export type AddCluster = (clusterOrModel: ClusterModel | Cluster) => Cluster;
const addClusterInjectable = getInjectable({
id: "add-cluster",
instantiate: (di): AddCluster => {
const clustersState = di.inject(clustersStateInjectable);
const emitAppEvent = di.inject(emitAppEventInjectable);
const readClusterConfigSync = di.inject(readClusterConfigSyncInjectable);
return action((clusterOrModel) => {
emitAppEvent({ name: "cluster", action: "add" });
const cluster = clusterOrModel instanceof Cluster
? clusterOrModel
: new Cluster(
clusterOrModel,
readClusterConfigSync(clusterOrModel),
);
clustersState.set(cluster.id, cluster);
return cluster;
});
},
});
export default addClusterInjectable;

View File

@ -0,0 +1,18 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import clustersStateInjectable from "./state.injectable";
const clustersInjectable = getInjectable({
id: "clusters",
instantiate: (di) => {
const clustersState = di.inject(clustersStateInjectable);
return computed(() => [...clustersState.values()]);
},
});
export default clustersInjectable;

View File

@ -3,18 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../cluster-types";
import type { Cluster } from "../cluster/cluster";
import clusterStoreInjectable from "./cluster-store.injectable";
import type { ClusterId } from "../../../../common/cluster-types";
import type { Cluster } from "../../../../common/cluster/cluster";
import clustersStateInjectable from "./state.injectable";
export type GetClusterById = (id: ClusterId) => Cluster | undefined;
const getClusterByIdInjectable = getInjectable({
id: "get-cluster-by-id",
instantiate: (di): GetClusterById => {
const store = di.inject(clusterStoreInjectable);
const clustersState = di.inject(clustersStateInjectable);
return (id) => store.getById(id);
return (id) => clustersState.get(id);
},
});

View File

@ -4,7 +4,7 @@
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { MigrationDeclaration } from "../persistent-storage/migrations.injectable";
import type { MigrationDeclaration } from "../../../../common/persistent-storage/migrations.injectable";
export const clusterStoreMigrationInjectionToken = getInjectionToken<MigrationDeclaration>({
id: "cluster-store-migration",

View File

@ -3,9 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterConfigData, ClusterModel } from "../cluster-types";
import readFileSyncInjectable from "../fs/read-file-sync.injectable";
import { loadConfigFromString, validateKubeConfig } from "../kube-helpers";
import type { ClusterConfigData, ClusterModel } from "../../../../common/cluster-types";
import readFileSyncInjectable from "../../../../common/fs/read-file-sync.injectable";
import { loadConfigFromString, validateKubeConfig } from "../../../../common/kube-helpers";
export type ReadClusterConfigSync = (model: ClusterModel) => ClusterConfigData;

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { observable } from "mobx";
import type { ClusterId } from "../../../../common/cluster-types";
import type { Cluster } from "../../../../common/cluster/cluster";
const clustersStateInjectable = getInjectable({
id: "clusters-state",
instantiate: () => observable.map<ClusterId, Cluster>(),
});
export default clustersStateInjectable;

View File

@ -0,0 +1,74 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { iter } from "@k8slens/utilities";
import { getInjectable } from "@ogre-tools/injectable";
import { comparer, action } from "mobx";
import { clusterStoreMigrationInjectionToken } from "./migration-token";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
import type { ClusterId, ClusterModel } from "../../../../common/cluster-types";
import { Cluster } from "../../../../common/cluster/cluster";
import loggerInjectable from "../../../../common/logger.injectable";
import createPersistentStorageInjectable from "../../../../common/persistent-storage/create.injectable";
import persistentStorageMigrationsInjectable from "../../../../common/persistent-storage/migrations.injectable";
import storeMigrationVersionInjectable from "../../../../common/vars/store-migration-version.injectable";
import clustersStateInjectable from "./state.injectable";
export interface ClusterStoreModel {
clusters?: ClusterModel[];
}
const clustersPersistentStorageInjectable = getInjectable({
id: "clusters-persistent-storage",
instantiate: (di) => {
const createPersistentStorage = di.inject(createPersistentStorageInjectable);
const readClusterConfigSync = di.inject(readClusterConfigSyncInjectable);
const clustersState = di.inject(clustersStateInjectable);
const logger = di.inject(loggerInjectable);
const storeMigrationVersion = di.inject(storeMigrationVersionInjectable);
const migrations = di.inject(persistentStorageMigrationsInjectable, clusterStoreMigrationInjectionToken);
return createPersistentStorage<ClusterStoreModel>({
configName: "lens-cluster-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: {
equals: comparer.structural,
},
projectVersion: storeMigrationVersion,
migrations,
fromStore: action(({ clusters = [] }) => {
const currentClusters = new Map(clustersState);
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,
readClusterConfigSync(clusterModel),
);
}
newClusters.set(clusterModel.id, cluster);
} catch (error) {
logger.warn(`[CLUSTER-STORE]: Failed to update/create a cluster: ${error}`);
}
}
clustersState.replace(newClusters);
}),
toJSON: () => ({
clusters: iter.chain(clustersState.values())
.map(cluster => cluster.toJSON())
.toArray(),
}),
});
},
});
export default clustersPersistentStorageInjectable;

View File

@ -3,17 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application";
import initUserStoreInjectable from "../../../../main/stores/init-user-store.injectable";
import clustersPersistentStorageInjectable from "../common/storage.injectable";
const initClusterStoreInjectable = getInjectable({
id: "init-cluster-store",
instantiate: (di) => ({
run: () => {
const clusterStore = di.inject(clusterStoreInjectable);
const storage = di.inject(clustersPersistentStorageInjectable);
clusterStore.load();
storage.loadAndStartSyncing();
},
runAfter: initUserStoreInjectable,
}),

View File

@ -3,17 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
import initUserStoreInjectable from "../../../../renderer/stores/init-user-store.injectable";
import clustersPersistentStorageInjectable from "../common/storage.injectable";
const initClusterStoreInjectable = getInjectable({
id: "init-cluster-store",
instantiate: (di) => ({
run: () => {
const clusterStore = di.inject(clusterStoreInjectable);
const storage = di.inject(clustersPersistentStorageInjectable);
clusterStore.load();
storage.loadAndStartSyncing();
},
runAfter: initUserStoreInjectable,
}),

View File

@ -13,7 +13,7 @@ import { frontEndRouteInjectionToken } from "../../common/front-end-routing/fron
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "./showing-kube-resources/common/allowed-resources-injection-token";
describe("cluster - visibility of sidebar items", () => {
let builder: ApplicationBuilder;

View File

@ -231,7 +231,7 @@ exports[`Showing correct entity settings renders 1`] = `
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -593,7 +593,7 @@ exports[`Showing correct entity settings when navigating to local cluster entity
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -976,7 +976,7 @@ exports[`Showing correct entity settings when navigating to non-local cluster en
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span
@ -1261,7 +1261,7 @@ exports[`Showing correct entity settings when navigating to weblink entity setti
class="HotbarSelector"
>
<i
class="Icon previous material interactive focusable"
class="Icon material interactive focusable"
tabindex="0"
>
<span

View File

@ -6,11 +6,11 @@
import type { DiContainer } from "@ogre-tools/injectable";
import type { RenderResult } from "@testing-library/react";
import { KubernetesCluster, WebLink } from "../../common/catalog-entities";
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { Cluster } from "../../common/cluster/cluster";
import navigateToEntitySettingsInjectable from "../../common/front-end-routing/routes/entity-settings/navigate-to-entity-settings.injectable";
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable";
import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import addClusterInjectable from "../cluster/storage/common/add.injectable";
describe("Showing correct entity settings", () => {
let builder: ApplicationBuilder;
@ -19,23 +19,11 @@ describe("Showing correct entity settings", () => {
let clusterEntity: KubernetesCluster;
let localClusterEntity: KubernetesCluster;
let otherEntity: WebLink;
let cluster: Cluster;
beforeEach(async () => {
builder = getApplicationBuilder();
builder.beforeWindowStart(({ windowDi }) => {
// TODO: remove once ClusterStore can be used without overriding it
windowDi.override(getClusterByIdInjectable, () => (clusterId) => {
if (clusterId === cluster.id) {
return cluster;
}
return undefined;
});
});
builder.afterWindowStart(({ windowDi }) => {
builder.afterWindowStart(async ({ windowDi }) => {
clusterEntity = new KubernetesCluster({
metadata: {
labels: {},
@ -78,14 +66,34 @@ describe("Showing correct entity settings", () => {
phase: "available",
},
});
cluster = new Cluster({
contextName: clusterEntity.spec.kubeconfigContext,
id: clusterEntity.getId(),
kubeConfigPath: clusterEntity.spec.kubeconfigPath,
}, {
clusterServerUrl: "https://localhost:9999",
const writeJsonFile = windowDi.inject(writeJsonFileInjectable);
const addCluster = windowDi.inject(addClusterInjectable);
await writeJsonFile(clusterEntity.spec.kubeconfigPath, {
contexts: [{
name: clusterEntity.spec.kubeconfigContext,
context: {
cluster: "some-cluster",
user: "some-user",
},
}],
clusters: [{
name: "some-cluster",
cluster: {
server: "https://localhost:9999",
},
}],
users: [{
name: "some-user",
}],
});
addCluster({
id: clusterEntity.getId(),
kubeConfigPath: clusterEntity.spec.kubeconfigPath,
contextName: clusterEntity.spec.kubeconfigContext,
});
// TODO: replace with proper entity source once syncing entities between main and windows is injectable
const catalogEntityRegistry = windowDi.inject(catalogEntityRegistryInjectable);

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
import initClusterStoreInjectable from "../../../cluster/store/renderer/init.injectable";
import initClusterStoreInjectable from "../../../cluster/storage/renderer/init.injectable";
const initHotbarStoreInjectable = getInjectable({
id: "init-hotbar-store",

View File

@ -19,7 +19,6 @@ import kubeconfigSyncManagerInjectable from "../kubeconfig-sync/manager.injectab
import type { KubeconfigSyncManager } from "../kubeconfig-sync/manager";
import type { KubeconfigSyncValue } from "../../../common/user-store";
import kubeconfigSyncsInjectable from "../../../common/user-store/kubeconfig-syncs.injectable";
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import type { AsyncFnMock } from "@async-fn/jest";
import type { Stat } from "../../../common/fs/stat.injectable";
@ -41,7 +40,6 @@ describe("kubeconfig-sync.source tests", () => {
let computeKubeconfigDiff: ComputeKubeconfigDiff;
let configToModels: ConfigToModels;
let kubeconfigSyncs: ObservableMap<string, KubeconfigSyncValue>;
let clusters: Map<string, Cluster>;
let di: DiContainer;
beforeEach(async () => {
@ -58,9 +56,6 @@ describe("kubeconfig-sync.source tests", () => {
ensurePath: async () => "/some-proxy-kubeconfig-file",
} as Partial<KubeconfigManager> as KubeconfigManager));
clusters = new Map();
di.override(getClusterByIdInjectable, () => id => clusters.get(id));
kubeconfigSyncs = observable.map();
di.override(kubeconfigSyncsInjectable, () => kubeconfigSyncs);

View File

@ -9,7 +9,6 @@ import { action } from "mobx";
import { homedir } from "os";
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
import type { CatalogEntity } from "../../../common/catalog";
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
import { Cluster } from "../../../common/cluster/cluster";
import { loadConfigFromString } from "../../../common/kube-helpers";
import clustersThatAreBeingDeletedInjectable from "../../cluster/are-being-deleted.injectable";
@ -17,6 +16,7 @@ import { catalogEntityFromCluster } from "../../cluster/manager";
import configToModelsInjectable from "./config-to-models.injectable";
import kubeconfigSyncLoggerInjectable from "./logger.injectable";
import clusterConnectionInjectable from "../../cluster/cluster-connection.injectable";
import getClusterByIdInjectable from "../../../features/cluster/storage/common/get-by-id.injectable";
export type ComputeKubeconfigDiff = (contents: string, source: ObservableMap<string, [Cluster, CatalogEntity]>, filePath: string) => void;

View File

@ -3,8 +3,10 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import clusterStoreInjectable from "../../common/cluster-store/cluster-store.injectable";
import loggerInjectable from "../../common/logger.injectable";
import addClusterInjectable from "../../features/cluster/storage/common/add.injectable";
import clustersInjectable from "../../features/cluster/storage/common/clusters.injectable";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable";
import clustersThatAreBeingDeletedInjectable from "./are-being-deleted.injectable";
import clusterConnectionInjectable from "./cluster-connection.injectable";
@ -17,11 +19,13 @@ const clusterManagerInjectable = getInjectable({
id: "cluster-manager",
instantiate: (di) => new ClusterManager({
store: di.inject(clusterStoreInjectable),
catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable),
clustersThatAreBeingDeleted: di.inject(clustersThatAreBeingDeletedInjectable),
visibleCluster: di.inject(visibleClusterInjectable),
logger: di.inject(loggerInjectable),
addCluster: di.inject(addClusterInjectable),
clusters: di.inject(clustersInjectable),
getClusterById: di.inject(getClusterByIdInjectable),
updateEntityMetadata: di.inject(updateEntityMetadataInjectable),
updateEntitySpec: di.inject(updateEntitySpecInjectable),
getClusterConnection: (cluster) => di.inject(clusterConnectionInjectable, cluster),

View File

@ -4,34 +4,37 @@
*/
import "../../common/ipc/cluster";
import type { IObservableValue, ObservableSet } from "mobx";
import type { IComputedValue, IObservableValue, ObservableSet } from "mobx";
import { action, makeObservable, observe, reaction, toJS } from "mobx";
import type { Cluster } from "../../common/cluster/cluster";
import { isErrnoException } from "@k8slens/utilities";
import { isKubernetesCluster, KubernetesCluster, LensKubernetesClusterStatus } from "../../common/catalog-entities/kubernetes-cluster";
import { ipcMainOn } from "../../common/ipc";
import { once } from "lodash";
import type { ClusterStore } from "../../common/cluster-store/cluster-store";
import type { ClusterId } from "../../common/cluster-types";
import type { CatalogEntityRegistry } from "../catalog";
import type { Logger } from "../../common/logger";
import type { UpdateEntityMetadata } from "./update-entity-metadata.injectable";
import type { UpdateEntitySpec } from "./update-entity-spec.injectable";
import type { ClusterConnection } from "./cluster-connection.injectable";
import type { GetClusterById } from "../../features/cluster/storage/common/get-by-id.injectable";
import type { AddCluster } from "../../features/cluster/storage/common/add.injectable";
const logPrefix = "[CLUSTER-MANAGER]:";
const lensSpecificClusterStatuses: Set<string> = new Set(Object.values(LensKubernetesClusterStatus));
interface Dependencies {
readonly store: ClusterStore;
readonly catalogEntityRegistry: CatalogEntityRegistry;
readonly clustersThatAreBeingDeleted: ObservableSet<ClusterId>;
readonly visibleCluster: IObservableValue<ClusterId | null>;
readonly logger: Logger;
readonly clusters: IComputedValue<Cluster[]>;
updateEntityMetadata: UpdateEntityMetadata;
updateEntitySpec: UpdateEntitySpec;
getClusterConnection: (cluster: Cluster) => ClusterConnection;
getClusterById: GetClusterById;
addCluster: AddCluster;
}
export class ClusterManager {
@ -42,15 +45,15 @@ export class ClusterManager {
init = once(() => {
// reacting to every cluster's state change and total amount of items
reaction(
() => this.dependencies.store.clustersList.get().map(c => c.getState()),
() => this.updateCatalog(this.dependencies.store.clustersList.get()),
() => this.dependencies.clusters.get().map(c => c.getState()),
() => this.updateCatalog(this.dependencies.clusters.get()),
{ fireImmediately: false },
);
// reacting to every cluster's preferences change and total amount of items
reaction(
() => this.dependencies.store.clustersList.get().map(c => toJS(c.preferences)),
() => this.updateCatalog(this.dependencies.store.clustersList.get()),
() => this.dependencies.clusters.get().map(c => toJS(c.preferences)),
() => this.updateCatalog(this.dependencies.clusters.get()),
{ fireImmediately: false },
);
@ -152,7 +155,7 @@ export class ClusterManager {
@action
protected syncClustersFromCatalog(entities: KubernetesCluster[]) {
for (const entity of entities) {
const cluster = this.dependencies.store.getById(entity.getId());
const cluster = this.dependencies.getClusterById(entity.getId());
if (!cluster) {
const model = {
@ -167,7 +170,7 @@ export class ClusterManager {
* Add the bare minimum of data to ClusterStore. And especially no
* preferences, as those might be configured by the entity's source
*/
this.dependencies.store.addCluster(model);
this.dependencies.addCluster(model);
} catch (error) {
if (isErrnoException(error) && error.code === "ENOENT" && error.path === entity.spec.kubeconfigPath) {
this.dependencies.logger.warn(`${logPrefix} kubeconfig file disappeared`, model);
@ -208,8 +211,8 @@ export class ClusterManager {
this.dependencies.logger.info(`${logPrefix} network is offline`);
await Promise.allSettled(
this.dependencies.store
.clustersList
this.dependencies
.clusters
.get()
.filter(cluster => !cluster.disconnected.get())
.map(async (cluster) => {
@ -227,8 +230,8 @@ export class ClusterManager {
this.dependencies.logger.info(`${logPrefix} network is online`);
await Promise.allSettled(
this.dependencies.store
.clustersList
this.dependencies
.clusters
.get()
.filter(cluster => !cluster.disconnected.get())
.map((cluster) => (
@ -240,7 +243,7 @@ export class ClusterManager {
};
stop() {
for (const cluster of this.dependencies.store.clustersList.get()) {
for (const cluster of this.dependencies.clusters.get()) {
this.dependencies
.getClusterConnection(cluster)
.disconnect();

View File

@ -18,7 +18,7 @@ interface Pre360ClusterModel extends ClusterModel {
}
import { getInjectable } from "@ogre-tools/injectable";
import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token";
import { clusterStoreMigrationInjectionToken } from "../../../features/cluster/storage/common/migration-token";
import readFileBufferSyncInjectable from "../../../common/fs/read-file-buffer-sync.injectable";
import loggerInjectable from "../../../common/logger.injectable";
import writeFileSyncInjectable from "../../../common/fs/write-file-sync.injectable";

View File

@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token";
import { clusterStoreMigrationInjectionToken } from "../../../features/cluster/storage/common/migration-token";
import type { ClusterModel } from "../../../common/cluster-types";
import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable";
import joinPathsInjectable from "../../../common/path/join-paths.injectable";

View File

@ -10,7 +10,7 @@ import { isDefined } from "@k8slens/utilities";
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../../../common/logger.injectable";
import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token";
import { clusterStoreMigrationInjectionToken } from "../../../features/cluster/storage/common/migration-token";
import { generateNewIdFor } from "../../../common/utils/generate-new-id-for";
interface Pre500ClusterModel extends ClusterModel {

View File

@ -6,7 +6,7 @@
// Fix embedded kubeconfig paths under snap config
import { getInjectable } from "@ogre-tools/injectable";
import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token";
import { clusterStoreMigrationInjectionToken } from "../../../features/cluster/storage/common/migration-token";
import loggerInjectable from "../../../common/logger.injectable";
import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable";
import type { ClusterModel } from "../../../common/cluster-types";

View File

@ -4,7 +4,7 @@
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { computed } from "mobx";
import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import type { KubeApiResourceDescriptor } from "../../common/rbac";
import { formatKubeApiResource } from "../../common/rbac";

View File

@ -5,12 +5,12 @@
import { getInjectable } from "@ogre-tools/injectable";
import { setupIpcMainHandlers } from "./setup-ipc-main-handlers";
import loggerInjectable from "../../../../common/logger.injectable";
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
import applicationMenuItemCompositeInjectable from "../../../../features/application-menu/main/application-menu-item-composite.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import pushCatalogToRendererInjectable from "../../../catalog-sync-to-renderer/push-catalog-to-renderer.injectable";
import clusterFramesInjectable from "../../../../common/cluster-frames.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import clustersInjectable from "../../../../features/cluster/storage/common/clusters.injectable";
const setupIpcMainHandlersInjectable = getInjectable({
id: "setup-ipc-main-handlers",
@ -24,7 +24,7 @@ const setupIpcMainHandlersInjectable = getInjectable({
setupIpcMainHandlers({
applicationMenuItemComposite: di.inject(applicationMenuItemCompositeInjectable),
pushCatalogToRenderer: di.inject(pushCatalogToRendererInjectable),
clusterStore: di.inject(clusterStoreInjectable),
clusters: di.inject(clustersInjectable),
getClusterById: di.inject(getClusterByIdInjectable),
clusterFrames: di.inject(clusterFramesInjectable),
});

View File

@ -7,7 +7,6 @@ import { BrowserWindow, Menu } from "electron";
import type { ClusterFrameInfo } from "../../../../common/cluster-frames.injectable";
import { clusterSetFrameIdHandler, clusterStates } from "../../../../common/ipc/cluster";
import type { ClusterId } from "../../../../common/cluster-types";
import type { ClusterStore } from "../../../../common/cluster-store/cluster-store";
import { broadcastMainChannel, broadcastMessage, ipcMainHandle, ipcMainOn } from "../../../../common/ipc";
import type { IComputedValue, ObservableMap } from "mobx";
import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel } from "../../../../common/ipc/window";
@ -16,21 +15,23 @@ import type { ApplicationMenuItemTypes } from "../../../../features/application-
import type { Composite } from "../../../../common/utils/composite/get-composite/get-composite";
import { getApplicationMenuTemplate } from "../../../../features/application-menu/main/populate-application-menu.injectable";
import type { MenuItemRoot } from "../../../../features/application-menu/main/application-menu-item-composite.injectable";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import type { Cluster } from "../../../../common/cluster/cluster";
interface Dependencies {
applicationMenuItemComposite: IComputedValue<Composite<ApplicationMenuItemTypes | MenuItemRoot>>;
clusterStore: ClusterStore;
getClusterById: GetClusterById;
pushCatalogToRenderer: () => void;
clusterFrames: ObservableMap<string, ClusterFrameInfo>;
clusters: IComputedValue<Cluster[]>;
}
export const setupIpcMainHandlers = ({
applicationMenuItemComposite,
clusterStore,
getClusterById,
pushCatalogToRenderer,
clusterFrames,
clusters,
}: Dependencies) => {
ipcMainHandle(clusterSetFrameIdHandler, (event: IpcMainInvokeEvent, clusterId: ClusterId) => {
const cluster = getClusterById(clusterId);
@ -60,7 +61,7 @@ export const setupIpcMainHandlers = ({
});
ipcMainHandle(clusterStates, () => (
clusterStore.clustersList.get().map(cluster => ({
clusters.get().map(cluster => ({
id: cluster.id,
state: cluster.getState(),
}))

View File

@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { kubectlApplyAllChannel } from "../../common/kube-helpers/channels";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable";
import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
@ -15,14 +15,16 @@ const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjecta
const getClusterById = di.inject(getClusterByIdInjectable);
const emitAppEvent = di.inject(emitAppEventInjectable);
return async ({
clusterId,
extraArgs,
resources,
}) => {
emitAppEvent({ name: "cluster", action: "kubectl-apply-all" });
return async (event) => {
const {
clusterId,
extraArgs,
resources,
} = event;
const cluster = getClusterById(clusterId);
emitAppEvent({ name: "cluster", action: "kubectl-apply-all" });
if (!cluster) {
return {
callWasSuccessful: false,

View File

@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { kubectlDeleteAllChannel } from "../../common/kube-helpers/channels";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable";
import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
@ -15,15 +15,16 @@ const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInject
const emitAppEvent = di.inject(emitAppEventInjectable);
const getClusterById = di.inject(getClusterByIdInjectable);
return async ({
clusterId,
extraArgs,
resources,
}) => {
emitAppEvent({ name: "cluster", action: "kubectl-delete-all" });
return async (event) => {
const {
clusterId,
extraArgs,
resources,
} = event;
const cluster = getClusterById(clusterId);
emitAppEvent({ name: "cluster", action: "kubectl-delete-all" });
if (!cluster) {
return {
callWasSuccessful: false,

View File

@ -3,9 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { getClusterIdFromHost } from "../../common/utils";
import { apiKubePrefix } from "../../common/vars";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
import type { GetClusterForRequest } from "./lens-proxy";
const getClusterForRequestInjectable = getInjectable({

View File

@ -3,7 +3,6 @@
* 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 "@k8slens/utilities";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
@ -17,6 +16,7 @@ import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable
import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable";
import loggerInjectable from "../../../common/logger.injectable";
import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable";
import type { ClusterStoreModel } from "../../../features/cluster/storage/common/storage.injectable";
const v503Beta1UserStoreMigrationInjectable = getInjectable({
id: "v5.0.3-beta.1-user-store-migration",

View File

@ -4,16 +4,24 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import catalogEntityRegistryInjectable from "./registry.injectable";
const activeEntityInternalClusterInjectable = getInjectable({
id: "active-entity-internal-cluster",
instantiate: (di) => {
const store = di.inject(clusterStoreInjectable);
const getClusterById = di.inject(getClusterByIdInjectable);
const entityRegistry = di.inject(catalogEntityRegistryInjectable);
return computed(() => store.getById(entityRegistry.activeEntity?.getId()));
return computed(() => {
const entityId = entityRegistry.activeEntity?.getId();
if (entityId) {
return getClusterById(entityId);
}
return undefined;
});
},
});

View File

@ -4,9 +4,9 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import catalogCategoryRegistryInjectable from "../../../common/catalog/category-registry.injectable";
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
import loadKubeconfigInjectable from "../../../common/cluster/load-kubeconfig.injectable";
import loggerInjectable from "../../../common/logger.injectable";
import getClusterByIdInjectable from "../../../features/cluster/storage/common/get-by-id.injectable";
import openDeleteClusterDialogInjectable from "../../components/delete-cluster-dialog/open.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../tokens";

View File

@ -4,16 +4,20 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import hostedClusterIdInjectable from "./hosted-cluster-id.injectable";
import clusterStoreInjectable from "../../common/cluster-store/cluster-store.injectable";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
const hostedClusterInjectable = getInjectable({
id: "hosted-cluster",
instantiate: (di) => {
const hostedClusterId = di.inject(hostedClusterIdInjectable);
const store = di.inject(clusterStoreInjectable);
const getClusterById = di.inject(getClusterByIdInjectable);
return store.getById(hostedClusterId);
if (!hostedClusterId) {
return undefined;
}
return getClusterById(hostedClusterId);
},
});

View File

@ -5,7 +5,7 @@
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { computed } from "mobx";
import hostedClusterInjectable from "./hosted-cluster.injectable";
import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import type { KubeApiResourceDescriptor } from "../../common/rbac";
import { formatKubeApiResource } from "../../common/rbac";

View File

@ -6,8 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import type { KubernetesCluster } from "../../../../common/catalog-entities";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterIconSetting } from "../../cluster-settings/icon-settings";
import { ClusterKubeconfig } from "../../cluster-settings/kubeconfig";
import { ClusterNameSetting } from "../../cluster-settings/name-setting";

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterMetricsSetting } from "../../cluster-settings/metrics-setting";
import { ClusterPrometheusSetting } from "../../cluster-settings/prometheus-setting";
import { ShowMetricsSetting } from "../../cluster-settings/show-metrics";

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterAccessibleNamespaces } from "../../cluster-settings/accessible-namespaces";
import type { EntitySettingViewProps } from "../extension-registrator.injectable";
import { entitySettingInjectionToken } from "../token";

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterNodeShellSetting } from "../../cluster-settings/node-shell-setting";
import type { EntitySettingViewProps } from "../extension-registrator.injectable";
import { entitySettingInjectionToken } from "../token";

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterProxySetting } from "../../cluster-settings/proxy-setting";
import type { EntitySettingViewProps } from "../extension-registrator.injectable";
import { entitySettingInjectionToken } from "../token";

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterLocalTerminalSetting } from "../../cluster-settings/local-terminal-settings";
import type { EntitySettingViewProps } from "../extension-registrator.injectable";
import { entitySettingInjectionToken } from "../token";

View File

@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import { shouldShowResourceInjectionToken } from "../../../../common/cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { byOrderNumber } from "../../../../common/utils/composable-responsibilities/orderable/orderable";
import { workloadInjectionToken } from "./workload-injection-token";

View File

@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
import loggerInjectable from "../../../common/logger.injectable";
import getClusterByIdInjectable from "../../../features/cluster/storage/common/get-by-id.injectable";
import { ClusterFrameHandler } from "./cluster-frame-handler";
import emitClusterVisibilityInjectable from "./emit-cluster-visibility.injectable";

View File

@ -9,8 +9,8 @@ import type { Disposer } from "@k8slens/utilities";
import { onceDefined } from "@k8slens/utilities";
import assert from "assert";
import type { Logger } from "../../../common/logger";
import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable";
import { getClusterFrameUrl } from "../../../common/utils";
import type { GetClusterById } from "../../../features/cluster/storage/common/get-by-id.injectable";
export interface LensView {
isLoaded: boolean;

View File

@ -18,10 +18,10 @@ import clusterViewRouteParametersInjectable from "./cluster-view-route-parameter
import clusterFrameHandlerInjectable from "./cluster-frame-handler.injectable";
import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry";
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable";
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
import type { RequestClusterActivation } from "../../../features/cluster/activation/common/request-token";
import requestClusterActivationInjectable from "../../../features/cluster/activation/renderer/request-activation.injectable";
import type { GetClusterById } from "../../../features/cluster/storage/common/get-by-id.injectable";
import getClusterByIdInjectable from "../../../features/cluster/storage/common/get-by-id.injectable";
interface Dependencies {
clusterId: IComputedValue<string>;

View File

@ -7,7 +7,7 @@ import { withInjectables } from "@ogre-tools/injectable-react";
import type { IComputedValue } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { shouldShowResourceInjectionToken } from "../../features/cluster/showing-kube-resources/common/allowed-resources-injection-token";
import { Events } from "../components/+events/events";
export interface WorkloadEventsProps {}

View File

@ -10,8 +10,8 @@ import type { IpcRendererEvent } from "electron";
import React from "react";
import notificationsStoreInjectable from "../components/notifications/notifications-store.injectable";
import { getMillisecondsFromUnixEpoch } from "../../common/utils/date/get-current-date-time";
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import showSuccessNotificationInjectable from "../components/notifications/show-success-notification.injectable";
import getClusterByIdInjectable from "../../features/cluster/storage/common/get-by-id.injectable";
const intervalBetweenNotifications = 1000 * 60; // 60s

View File

@ -12,11 +12,9 @@ import navigateToExtensionsInjectable from "../../../common/front-end-routing/ro
import navigateToEntitySettingsInjectable from "../../../common/front-end-routing/routes/entity-settings/navigate-to-entity-settings.injectable";
import navigateToClusterViewInjectable from "../../../common/front-end-routing/routes/cluster-view/navigate-to-cluster-view.injectable";
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
// TODO: Importing from features is not OK. Make protocol-router to comply with Open Closed Principle to allow moving implementation under a feature
import navigateToPreferencesInjectable from "../../../features/preferences/common/navigate-to-preferences.injectable";
import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable";
import showShortInfoNotificationInjectable from "../../components/notifications/show-short-info.injectable";
import getClusterByIdInjectable from "../../../features/cluster/storage/common/get-by-id.injectable";
const bindProtocolAddRouteHandlersInjectable = getInjectable({
id: "bind-protocol-add-route-handlers",

View File

@ -17,7 +17,7 @@ import type { NavigateToEntitySettings } from "../../../common/front-end-routing
import type { NavigateToClusterView } from "../../../common/front-end-routing/routes/cluster-view/navigate-to-cluster-view.injectable";
import assert from "assert";
import type { AttemptInstallByInfo } from "../../components/+extensions/attempt-install-by-info.injectable";
import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable";
import type { GetClusterById } from "../../../features/cluster/storage/common/get-by-id.injectable";
interface Dependencies {
attemptInstallByInfo: AttemptInstallByInfo;