mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Move cluster related types and function into seperate files (#3530)
This commit is contained in:
parent
2893ad956d
commit
a6e91fc34a
@ -25,9 +25,11 @@ import yaml from "js-yaml";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
import { Cluster } from "../../main/cluster";
|
import { Cluster } from "../../main/cluster";
|
||||||
import { ClusterId, ClusterStore, getClusterIdFromHost } from "../cluster-store";
|
import { ClusterStore } from "../cluster-store";
|
||||||
import { Console } from "console";
|
import { Console } from "console";
|
||||||
import { stdout, stderr } from "process";
|
import { stdout, stderr } from "process";
|
||||||
|
import type { ClusterId } from "../cluster-types";
|
||||||
|
import { getCustomKubeConfigPath } from "../utils";
|
||||||
|
|
||||||
console = new Console(stdout, stderr);
|
console = new Console(stdout, stderr);
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ users:
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
function embed(clusterId: ClusterId, contents: any): string {
|
function embed(clusterId: ClusterId, contents: any): string {
|
||||||
const absPath = ClusterStore.getCustomKubeConfigPath(clusterId);
|
const absPath = getCustomKubeConfigPath(clusterId);
|
||||||
|
|
||||||
fse.ensureDirSync(path.dirname(absPath));
|
fse.ensureDirSync(path.dirname(absPath));
|
||||||
fse.writeFileSync(absPath, contents, { encoding: "utf-8", mode: 0o600 });
|
fse.writeFileSync(absPath, contents, { encoding: "utf-8", mode: 0o600 });
|
||||||
@ -550,27 +552,3 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
|
|||||||
expect(icon.startsWith("data:;base64,")).toBe(true);
|
expect(icon.startsWith("data:;base64,")).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getClusterIdFromHost", () => {
|
|
||||||
const clusterFakeId = "fe540901-0bd6-4f6c-b472-bce1559d7c4a";
|
|
||||||
|
|
||||||
it("should return undefined for non cluster frame hosts", () => {
|
|
||||||
expect(getClusterIdFromHost("localhost:45345")).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return ClusterId for cluster frame hosts", () => {
|
|
||||||
expect(getClusterIdFromHost(`${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return ClusterId for cluster frame hosts with additional subdomains", () => {
|
|
||||||
expect(getClusterIdFromHost(`abc.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.yz.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@ -19,119 +19,26 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import path from "path";
|
import { ipcMain, ipcRenderer, webFrame } from "electron";
|
||||||
import { app, ipcMain, ipcRenderer, remote, webFrame } from "electron";
|
|
||||||
import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
|
import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
|
||||||
import { BaseStore } from "./base-store";
|
import { BaseStore } from "./base-store";
|
||||||
import { Cluster, ClusterState } from "../main/cluster";
|
import { Cluster } from "../main/cluster";
|
||||||
import migrations from "../migrations/cluster-store";
|
import migrations from "../migrations/cluster-store";
|
||||||
import * as uuid from "uuid";
|
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import { appEventBus } from "./event-bus";
|
import { appEventBus } from "./event-bus";
|
||||||
import { ipcMainHandle, ipcMainOn, ipcRendererOn, requestMain } from "./ipc";
|
import { ipcMainHandle, ipcMainOn, ipcRendererOn, requestMain } from "./ipc";
|
||||||
import { disposer, toJS } from "./utils";
|
import { disposer, toJS } from "./utils";
|
||||||
|
import type { ClusterModel, ClusterId, ClusterState } from "./cluster-types";
|
||||||
export interface ClusterIconUpload {
|
|
||||||
clusterId: string;
|
|
||||||
name: string;
|
|
||||||
path: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterMetadata {
|
|
||||||
[key: string]: string | number | boolean | object;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ClusterPrometheusMetadata = {
|
|
||||||
success?: boolean;
|
|
||||||
provider?: string;
|
|
||||||
autoDetected?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ClusterStoreModel {
|
export interface ClusterStoreModel {
|
||||||
clusters?: ClusterModel[];
|
clusters?: ClusterModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ClusterId = string;
|
|
||||||
|
|
||||||
export interface UpdateClusterModel extends Omit<ClusterModel, "id"> {
|
|
||||||
id?: ClusterId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterModel {
|
|
||||||
/** Unique id for a cluster */
|
|
||||||
id: ClusterId;
|
|
||||||
|
|
||||||
/** Path to cluster kubeconfig */
|
|
||||||
kubeConfigPath: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Workspace id
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
workspace?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated this is used only for hotbar migrations from 4.2.X
|
|
||||||
*/
|
|
||||||
workspaces?: string[];
|
|
||||||
|
|
||||||
/** User context in kubeconfig */
|
|
||||||
contextName: string;
|
|
||||||
|
|
||||||
/** Preferences */
|
|
||||||
preferences?: ClusterPreferences;
|
|
||||||
|
|
||||||
/** Metadata */
|
|
||||||
metadata?: ClusterMetadata;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Labels for the catalog entity
|
|
||||||
*/
|
|
||||||
labels?: Record<string, string>;
|
|
||||||
|
|
||||||
/** List of accessible namespaces */
|
|
||||||
accessibleNamespaces?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterPreferences extends ClusterPrometheusPreferences {
|
|
||||||
terminalCWD?: string;
|
|
||||||
clusterName?: string;
|
|
||||||
iconOrder?: number;
|
|
||||||
icon?: string;
|
|
||||||
httpsProxy?: string;
|
|
||||||
hiddenMetrics?: string[];
|
|
||||||
nodeShellImage?: string;
|
|
||||||
imagePullSecret?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterPrometheusPreferences {
|
|
||||||
prometheus?: {
|
|
||||||
namespace: string;
|
|
||||||
service: string;
|
|
||||||
port: number;
|
|
||||||
prefix: string;
|
|
||||||
};
|
|
||||||
prometheusProvider?: {
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialStates = "cluster:states";
|
const initialStates = "cluster:states";
|
||||||
|
|
||||||
export const initialNodeShellImage = "docker.io/alpine:3.13";
|
|
||||||
|
|
||||||
export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||||
private static StateChannel = "cluster:state";
|
private static StateChannel = "cluster:state";
|
||||||
|
|
||||||
static get storedKubeConfigFolder(): string {
|
|
||||||
return path.resolve((app ?? remote.app).getPath("userData"), "kubeconfigs");
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCustomKubeConfigPath(clusterId: ClusterId = uuid.v4()): string {
|
|
||||||
return path.resolve(ClusterStore.storedKubeConfigFolder, clusterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
clusters = observable.map<ClusterId, Cluster>();
|
clusters = observable.map<ClusterId, Cluster>();
|
||||||
removedClusters = observable.map<ClusterId, Cluster>();
|
removedClusters = observable.map<ClusterId, Cluster>();
|
||||||
|
|
||||||
@ -272,22 +179,3 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getClusterIdFromHost(host: string): ClusterId | undefined {
|
|
||||||
// e.g host == "%clusterId.localhost:45345"
|
|
||||||
const subDomains = host.split(":")[0].split(".");
|
|
||||||
|
|
||||||
return subDomains.slice(-2, -1)[0]; // ClusterId or undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getClusterFrameUrl(clusterId: ClusterId) {
|
|
||||||
return `//${clusterId}.${location.host}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHostedClusterId() {
|
|
||||||
return getClusterIdFromHost(location.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHostedCluster(): Cluster {
|
|
||||||
return ClusterStore.getInstance().getById(getHostedClusterId());
|
|
||||||
}
|
|
||||||
|
|||||||
180
src/common/cluster-types.ts
Normal file
180
src/common/cluster-types.ts
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON serializable metadata type
|
||||||
|
*/
|
||||||
|
export type ClusterMetadata = Record<string, string | number | boolean | object>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata for cluster's prometheus settings
|
||||||
|
*/
|
||||||
|
export interface ClusterPrometheusMetadata {
|
||||||
|
success?: boolean;
|
||||||
|
provider?: string;
|
||||||
|
autoDetected?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ClusterId is an opaque string
|
||||||
|
*/
|
||||||
|
export type ClusterId = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fields that are used for updating a cluster instance
|
||||||
|
*/
|
||||||
|
export type UpdateClusterModel = Omit<ClusterModel, "id">;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model for passing cluster data around, including to disk
|
||||||
|
*/
|
||||||
|
export interface ClusterModel {
|
||||||
|
/** Unique id for a cluster */
|
||||||
|
id: ClusterId;
|
||||||
|
|
||||||
|
/** Path to cluster kubeconfig */
|
||||||
|
kubeConfigPath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workspace id
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
workspace?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated this is used only for hotbar migrations from 4.2.X
|
||||||
|
*/
|
||||||
|
workspaces?: string[];
|
||||||
|
|
||||||
|
/** User context in kubeconfig */
|
||||||
|
contextName: string;
|
||||||
|
|
||||||
|
/** Preferences */
|
||||||
|
preferences?: ClusterPreferences;
|
||||||
|
|
||||||
|
/** Metadata */
|
||||||
|
metadata?: ClusterMetadata;
|
||||||
|
|
||||||
|
/** List of accessible namespaces */
|
||||||
|
accessibleNamespaces?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Labels for the catalog entity
|
||||||
|
*/
|
||||||
|
labels?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The complete set of cluster settings or preferences
|
||||||
|
*/
|
||||||
|
export interface ClusterPreferences extends ClusterPrometheusPreferences {
|
||||||
|
terminalCWD?: string;
|
||||||
|
clusterName?: string;
|
||||||
|
iconOrder?: number;
|
||||||
|
icon?: string;
|
||||||
|
httpsProxy?: string;
|
||||||
|
hiddenMetrics?: string[];
|
||||||
|
nodeShellImage?: string;
|
||||||
|
imagePullSecret?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cluster's prometheus settings (a subset of cluster settings)
|
||||||
|
*/
|
||||||
|
export interface ClusterPrometheusPreferences {
|
||||||
|
prometheus?: {
|
||||||
|
namespace: string;
|
||||||
|
service: string;
|
||||||
|
port: number;
|
||||||
|
prefix: string;
|
||||||
|
};
|
||||||
|
prometheusProvider?: {
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The options for the status of connection attempts to a cluster
|
||||||
|
*/
|
||||||
|
export enum ClusterStatus {
|
||||||
|
AccessGranted = 2,
|
||||||
|
AccessDenied = 1,
|
||||||
|
Offline = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The OpenLens known static metadata keys
|
||||||
|
*/
|
||||||
|
export enum ClusterMetadataKey {
|
||||||
|
VERSION = "version",
|
||||||
|
CLUSTER_ID = "id",
|
||||||
|
DISTRIBUTION = "distribution",
|
||||||
|
NODES_COUNT = "nodes",
|
||||||
|
LAST_SEEN = "lastSeen",
|
||||||
|
PROMETHEUS = "prometheus"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A shorthand enum for resource types that have metrics attached to them via OpenLens metrics stack
|
||||||
|
*/
|
||||||
|
export enum ClusterMetricsResourceType {
|
||||||
|
Cluster = "Cluster",
|
||||||
|
Node = "Node",
|
||||||
|
Pod = "Pod",
|
||||||
|
Deployment = "Deployment",
|
||||||
|
StatefulSet = "StatefulSet",
|
||||||
|
Container = "Container",
|
||||||
|
Ingress = "Ingress",
|
||||||
|
VolumeClaim = "VolumeClaim",
|
||||||
|
ReplicaSet = "ReplicaSet",
|
||||||
|
DaemonSet = "DaemonSet",
|
||||||
|
Job = "Job",
|
||||||
|
Namespace = "Namespace",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default node shell image
|
||||||
|
*/
|
||||||
|
export const initialNodeShellImage = "docker.io/alpine:3.13";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments for requesting to refresh a cluster's metadata
|
||||||
|
*/
|
||||||
|
export interface ClusterRefreshOptions {
|
||||||
|
refreshMetadata?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data representing a cluster's state, for passing between main and renderer
|
||||||
|
*/
|
||||||
|
export interface ClusterState {
|
||||||
|
apiUrl: string;
|
||||||
|
online: boolean;
|
||||||
|
disconnected: boolean;
|
||||||
|
accessible: boolean;
|
||||||
|
ready: boolean;
|
||||||
|
failureReason: string;
|
||||||
|
isAdmin: boolean;
|
||||||
|
allowedNamespaces: string[]
|
||||||
|
allowedResources: string[]
|
||||||
|
isGlobalWatchEnabled: boolean;
|
||||||
|
}
|
||||||
@ -19,7 +19,8 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getHostedCluster } from "./cluster-store";
|
import { ClusterStore } from "./cluster-store";
|
||||||
|
import { getHostedClusterId } from "./utils";
|
||||||
|
|
||||||
export type KubeResource =
|
export type KubeResource =
|
||||||
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
||||||
@ -78,7 +79,7 @@ export function isAllowedResource(resources: KubeResource | KubeResource[]) {
|
|||||||
if (!Array.isArray(resources)) {
|
if (!Array.isArray(resources)) {
|
||||||
resources = [resources];
|
resources = [resources];
|
||||||
}
|
}
|
||||||
const { allowedResources = [] } = getHostedCluster() || {};
|
const { allowedResources = [] } = ClusterStore.getInstance().getById(getHostedClusterId()) || {};
|
||||||
|
|
||||||
for (const resource of resources) {
|
for (const resource of resources) {
|
||||||
if (!allowedResources.includes(resource)) {
|
if (!allowedResources.includes(resource)) {
|
||||||
|
|||||||
46
src/common/utils/__tests__/cluster-id-url-parsing.test.ts
Normal file
46
src/common/utils/__tests__/cluster-id-url-parsing.test.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getClusterIdFromHost } from "../cluster-id-url-parsing";
|
||||||
|
|
||||||
|
describe("getClusterIdFromHost", () => {
|
||||||
|
const clusterFakeId = "fe540901-0bd6-4f6c-b472-bce1559d7c4a";
|
||||||
|
|
||||||
|
it("should return undefined for non cluster frame hosts", () => {
|
||||||
|
expect(getClusterIdFromHost("localhost:45345")).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return ClusterId for cluster frame hosts", () => {
|
||||||
|
expect(getClusterIdFromHost(`${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return ClusterId for cluster frame hosts with additional subdomains", () => {
|
||||||
|
expect(getClusterIdFromHost(`abc.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.yz.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
});
|
||||||
|
});
|
||||||
50
src/common/utils/cluster-id-url-parsing.ts
Normal file
50
src/common/utils/cluster-id-url-parsing.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ClusterId } from "../cluster-types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab the `ClusterId` out of a host that was generated by `getClusterFrameUrl`, or nothing
|
||||||
|
* @param host The host section of a URL
|
||||||
|
* @returns The `ClusterId` part of the host, or `undefined`
|
||||||
|
*/
|
||||||
|
export function getClusterIdFromHost(host: string): ClusterId | undefined {
|
||||||
|
// e.g host == "%clusterId.localhost:45345"
|
||||||
|
const subDomains = host.split(":")[0].split(".");
|
||||||
|
|
||||||
|
return subDomains.slice(-2, -1)[0]; // ClusterId or undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the OpenLens backend routing host for a given `ClusterId`
|
||||||
|
* @param clusterId The ID to put in front of the current host
|
||||||
|
* @returns a new URL host section
|
||||||
|
*/
|
||||||
|
export function getClusterFrameUrl(clusterId: ClusterId) {
|
||||||
|
return `//${clusterId}.${location.host}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of `getClusterIdFromHost` from the current `location.host`
|
||||||
|
*/
|
||||||
|
export function getHostedClusterId(): ClusterId | undefined {
|
||||||
|
return getClusterIdFromHost(location.host);
|
||||||
|
}
|
||||||
@ -31,6 +31,7 @@ export * from "./autobind";
|
|||||||
export * from "./base64";
|
export * from "./base64";
|
||||||
export * from "./camelCase";
|
export * from "./camelCase";
|
||||||
export * from "./cloneJson";
|
export * from "./cloneJson";
|
||||||
|
export * from "./cluster-id-url-parsing";
|
||||||
export * from "./debouncePromise";
|
export * from "./debouncePromise";
|
||||||
export * from "./defineGlobal";
|
export * from "./defineGlobal";
|
||||||
export * from "./delay";
|
export * from "./delay";
|
||||||
@ -40,6 +41,7 @@ export * from "./escapeRegExp";
|
|||||||
export * from "./extended-map";
|
export * from "./extended-map";
|
||||||
export * from "./getRandId";
|
export * from "./getRandId";
|
||||||
export * from "./hash-set";
|
export * from "./hash-set";
|
||||||
|
export * from "./local-kubeconfig";
|
||||||
export * from "./n-fircate";
|
export * from "./n-fircate";
|
||||||
export * from "./openExternal";
|
export * from "./openExternal";
|
||||||
export * from "./paths";
|
export * from "./paths";
|
||||||
@ -51,6 +53,7 @@ export * from "./tar";
|
|||||||
export * from "./toggle-set";
|
export * from "./toggle-set";
|
||||||
export * from "./toJS";
|
export * from "./toJS";
|
||||||
export * from "./type-narrowing";
|
export * from "./type-narrowing";
|
||||||
|
export * from "./types";
|
||||||
|
|
||||||
import * as iter from "./iter";
|
import * as iter from "./iter";
|
||||||
|
|
||||||
|
|||||||
33
src/common/utils/local-kubeconfig.ts
Normal file
33
src/common/utils/local-kubeconfig.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { app, remote } from "electron";
|
||||||
|
import path from "path";
|
||||||
|
import * as uuid from "uuid";
|
||||||
|
import type { ClusterId } from "../cluster-types";
|
||||||
|
|
||||||
|
export function storedKubeConfigFolder(): string {
|
||||||
|
return path.resolve((app || remote.app).getPath("userData"), "kubeconfigs");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCustomKubeConfigPath(clusterId: ClusterId = uuid.v4()): string {
|
||||||
|
return path.resolve(storedKubeConfigFolder(), clusterId);
|
||||||
|
}
|
||||||
26
src/common/utils/types.ts
Normal file
26
src/common/utils/types.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An N length tuple of T
|
||||||
|
*/
|
||||||
|
export type Tuple<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never;
|
||||||
|
type _TupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N ? R : _TupleOf<T, N, [T, ...R]>;
|
||||||
@ -24,9 +24,9 @@ import { EventEmitter } from "events";
|
|||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
import { action, computed, makeObservable, observable, observe, reaction, when } from "mobx";
|
import { action, computed, makeObservable, observable, observe, reaction, when } from "mobx";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { getHostedCluster } from "../common/cluster-store";
|
import { ClusterStore } from "../common/cluster-store";
|
||||||
import { broadcastMessage, ipcMainOn, ipcRendererOn, requestMain, ipcMainHandle } from "../common/ipc";
|
import { broadcastMessage, ipcMainOn, ipcRendererOn, requestMain, ipcMainHandle } from "../common/ipc";
|
||||||
import { Disposer, Singleton, toJS } from "../common/utils";
|
import { Disposer, getHostedClusterId, Singleton, toJS } from "../common/utils";
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import type { InstalledExtension } from "./extension-discovery";
|
import type { InstalledExtension } from "./extension-discovery";
|
||||||
import { ExtensionsStore } from "./extensions-store";
|
import { ExtensionsStore } from "./extensions-store";
|
||||||
@ -296,7 +296,7 @@ export class ExtensionLoader extends Singleton {
|
|||||||
|
|
||||||
loadOnClusterRenderer() {
|
loadOnClusterRenderer() {
|
||||||
logger.debug(`${logModule}: load on cluster renderer (dashboard)`);
|
logger.debug(`${logModule}: load on cluster renderer (dashboard)`);
|
||||||
const cluster = getHostedCluster();
|
const cluster = ClusterStore.getInstance().getById(getHostedClusterId());
|
||||||
|
|
||||||
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
||||||
if ((await extension.isEnabledForCluster(cluster)) === false) {
|
if ((await extension.isEnabledForCluster(cluster)) === false) {
|
||||||
|
|||||||
@ -27,18 +27,19 @@ import fs from "fs";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
import type stream from "stream";
|
import type stream from "stream";
|
||||||
import { Disposer, ExtendedObservableMap, iter, Singleton } from "../../common/utils";
|
import { Disposer, ExtendedObservableMap, iter, Singleton, storedKubeConfigFolder } from "../../common/utils";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import type { KubeConfig } from "@kubernetes/client-node";
|
import type { KubeConfig } from "@kubernetes/client-node";
|
||||||
import { loadConfigFromString, splitConfig } from "../../common/kube-helpers";
|
import { loadConfigFromString, splitConfig } from "../../common/kube-helpers";
|
||||||
import { Cluster } from "../cluster";
|
import { Cluster } from "../cluster";
|
||||||
import { catalogEntityFromCluster, ClusterManager } from "../cluster-manager";
|
import { catalogEntityFromCluster, ClusterManager } from "../cluster-manager";
|
||||||
import { UserStore } from "../../common/user-store";
|
import { UserStore } from "../../common/user-store";
|
||||||
import { ClusterStore, UpdateClusterModel } from "../../common/cluster-store";
|
import { ClusterStore } from "../../common/cluster-store";
|
||||||
import { createHash } from "crypto";
|
import { createHash } from "crypto";
|
||||||
import { homedir } from "os";
|
import { homedir } from "os";
|
||||||
import globToRegExp from "glob-to-regexp";
|
import globToRegExp from "glob-to-regexp";
|
||||||
import { inspect } from "util";
|
import { inspect } from "util";
|
||||||
|
import type { UpdateClusterModel } from "../../common/cluster-types";
|
||||||
|
|
||||||
const logPrefix = "[KUBECONFIG-SYNC]:";
|
const logPrefix = "[KUBECONFIG-SYNC]:";
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ export class KubeconfigSyncManager extends Singleton {
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
// This must be done so that c&p-ed clusters are visible
|
// This must be done so that c&p-ed clusters are visible
|
||||||
this.startNewSync(ClusterStore.storedKubeConfigFolder);
|
this.startNewSync(storedKubeConfigFolder());
|
||||||
|
|
||||||
for (const filePath of UserStore.getInstance().syncKubeconfigEntries.keys()) {
|
for (const filePath of UserStore.getInstance().syncKubeconfigEntries.keys()) {
|
||||||
this.startNewSync(filePath);
|
this.startNewSync(filePath);
|
||||||
@ -216,7 +217,7 @@ export function computeDiff(contents: string, source: RootSource, filePath: stri
|
|||||||
|
|
||||||
const entity = catalogEntityFromCluster(cluster);
|
const entity = catalogEntityFromCluster(cluster);
|
||||||
|
|
||||||
if (!filePath.startsWith(ClusterStore.storedKubeConfigFolder)) {
|
if (!filePath.startsWith(storedKubeConfigFolder())) {
|
||||||
entity.metadata.labels.file = filePath.replace(homedir(), "~");
|
entity.metadata.labels.file = filePath.replace(homedir(), "~");
|
||||||
}
|
}
|
||||||
source.set(contextName, [cluster, entity]);
|
source.set(contextName, [cluster, entity]);
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
import { BaseClusterDetector } from "./base-cluster-detector";
|
import { BaseClusterDetector } from "./base-cluster-detector";
|
||||||
import { createHash } from "crypto";
|
import { createHash } from "crypto";
|
||||||
import { ClusterMetadataKey } from "../cluster";
|
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||||
|
|
||||||
export class ClusterIdDetector extends BaseClusterDetector {
|
export class ClusterIdDetector extends BaseClusterDetector {
|
||||||
key = ClusterMetadataKey.CLUSTER_ID;
|
key = ClusterMetadataKey.CLUSTER_ID;
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import type { ClusterMetadata } from "../../common/cluster-store";
|
import type { ClusterMetadata } from "../../common/cluster-types";
|
||||||
import type { Cluster } from "../cluster";
|
import type { Cluster } from "../cluster";
|
||||||
import type { BaseClusterDetector, ClusterDetectionResult } from "./base-cluster-detector";
|
import type { BaseClusterDetector, ClusterDetectionResult } from "./base-cluster-detector";
|
||||||
import { ClusterIdDetector } from "./cluster-id-detector";
|
import { ClusterIdDetector } from "./cluster-id-detector";
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { BaseClusterDetector } from "./base-cluster-detector";
|
import { BaseClusterDetector } from "./base-cluster-detector";
|
||||||
import { ClusterMetadataKey } from "../cluster";
|
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||||
|
|
||||||
export class DistributionDetector extends BaseClusterDetector {
|
export class DistributionDetector extends BaseClusterDetector {
|
||||||
key = ClusterMetadataKey.DISTRIBUTION;
|
key = ClusterMetadataKey.DISTRIBUTION;
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { BaseClusterDetector } from "./base-cluster-detector";
|
import { BaseClusterDetector } from "./base-cluster-detector";
|
||||||
import { ClusterMetadataKey } from "../cluster";
|
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||||
|
|
||||||
export class LastSeenDetector extends BaseClusterDetector {
|
export class LastSeenDetector extends BaseClusterDetector {
|
||||||
key = ClusterMetadataKey.LAST_SEEN;
|
key = ClusterMetadataKey.LAST_SEEN;
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { BaseClusterDetector } from "./base-cluster-detector";
|
import { BaseClusterDetector } from "./base-cluster-detector";
|
||||||
import { ClusterMetadataKey } from "../cluster";
|
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||||
|
|
||||||
export class NodesCountDetector extends BaseClusterDetector {
|
export class NodesCountDetector extends BaseClusterDetector {
|
||||||
key = ClusterMetadataKey.NODES_COUNT;
|
key = ClusterMetadataKey.NODES_COUNT;
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { BaseClusterDetector } from "./base-cluster-detector";
|
import { BaseClusterDetector } from "./base-cluster-detector";
|
||||||
import { ClusterMetadataKey } from "../cluster";
|
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||||
|
|
||||||
export class VersionDetector extends BaseClusterDetector {
|
export class VersionDetector extends BaseClusterDetector {
|
||||||
key = ClusterMetadataKey.VERSION;
|
key = ClusterMetadataKey.VERSION;
|
||||||
|
|||||||
@ -22,15 +22,16 @@
|
|||||||
import "../common/cluster-ipc";
|
import "../common/cluster-ipc";
|
||||||
import type http from "http";
|
import type http from "http";
|
||||||
import { action, autorun, makeObservable, observable, observe, reaction, toJS } from "mobx";
|
import { action, autorun, makeObservable, observable, observe, reaction, toJS } from "mobx";
|
||||||
import { ClusterId, ClusterStore, getClusterIdFromHost } from "../common/cluster-store";
|
|
||||||
import { Cluster } from "./cluster";
|
import { Cluster } from "./cluster";
|
||||||
import logger from "./logger";
|
import logger from "./logger";
|
||||||
import { apiKubePrefix } from "../common/vars";
|
import { apiKubePrefix } from "../common/vars";
|
||||||
import { Singleton } from "../common/utils";
|
import { getClusterIdFromHost, Singleton } from "../common/utils";
|
||||||
import { catalogEntityRegistry } from "./catalog";
|
import { catalogEntityRegistry } from "./catalog";
|
||||||
import { KubernetesCluster, KubernetesClusterPrometheusMetrics, KubernetesClusterStatusPhase } from "../common/catalog-entities/kubernetes-cluster";
|
import { KubernetesCluster, KubernetesClusterPrometheusMetrics, KubernetesClusterStatusPhase } from "../common/catalog-entities/kubernetes-cluster";
|
||||||
import { ipcMainOn } from "../common/ipc";
|
import { ipcMainOn } from "../common/ipc";
|
||||||
import { once } from "lodash";
|
import { once } from "lodash";
|
||||||
|
import { ClusterStore } from "../common/cluster-store";
|
||||||
|
import type { ClusterId } from "../common/cluster-types";
|
||||||
|
|
||||||
const logPrefix = "[CLUSTER-MANAGER]:";
|
const logPrefix = "[CLUSTER-MANAGER]:";
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ipcMain } from "electron";
|
import { ipcMain } from "electron";
|
||||||
import type { ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel } from "../common/cluster-store";
|
|
||||||
import { action, comparer, computed, makeObservable, observable, reaction, when } from "mobx";
|
import { action, comparer, computed, makeObservable, observable, reaction, when } from "mobx";
|
||||||
import { broadcastMessage, ClusterListNamespaceForbiddenChannel } from "../common/ipc";
|
import { broadcastMessage, ClusterListNamespaceForbiddenChannel } from "../common/ipc";
|
||||||
import { ContextHandler } from "./context-handler";
|
import { ContextHandler } from "./context-handler";
|
||||||
@ -34,54 +33,7 @@ import { VersionDetector } from "./cluster-detectors/version-detector";
|
|||||||
import { detectorRegistry } from "./cluster-detectors/detector-registry";
|
import { detectorRegistry } from "./cluster-detectors/detector-registry";
|
||||||
import plimit from "p-limit";
|
import plimit from "p-limit";
|
||||||
import { toJS } from "../common/utils";
|
import { toJS } from "../common/utils";
|
||||||
import { initialNodeShellImage } from "../common/cluster-store";
|
import { initialNodeShellImage, ClusterState, ClusterMetadataKey, ClusterRefreshOptions, ClusterStatus, ClusterMetricsResourceType, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel } from "../common/cluster-types";
|
||||||
|
|
||||||
export enum ClusterStatus {
|
|
||||||
AccessGranted = 2,
|
|
||||||
AccessDenied = 1,
|
|
||||||
Offline = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ClusterMetadataKey {
|
|
||||||
VERSION = "version",
|
|
||||||
CLUSTER_ID = "id",
|
|
||||||
DISTRIBUTION = "distribution",
|
|
||||||
NODES_COUNT = "nodes",
|
|
||||||
LAST_SEEN = "lastSeen",
|
|
||||||
PROMETHEUS = "prometheus"
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ClusterMetricsResourceType {
|
|
||||||
Cluster = "Cluster",
|
|
||||||
Node = "Node",
|
|
||||||
Pod = "Pod",
|
|
||||||
Deployment = "Deployment",
|
|
||||||
StatefulSet = "StatefulSet",
|
|
||||||
Container = "Container",
|
|
||||||
Ingress = "Ingress",
|
|
||||||
VolumeClaim = "VolumeClaim",
|
|
||||||
ReplicaSet = "ReplicaSet",
|
|
||||||
DaemonSet = "DaemonSet",
|
|
||||||
Job = "Job",
|
|
||||||
Namespace = "Namespace"
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ClusterRefreshOptions = {
|
|
||||||
refreshMetadata?: boolean
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ClusterState {
|
|
||||||
apiUrl: string;
|
|
||||||
online: boolean;
|
|
||||||
disconnected: boolean;
|
|
||||||
accessible: boolean;
|
|
||||||
ready: boolean;
|
|
||||||
failureReason: string;
|
|
||||||
isAdmin: boolean;
|
|
||||||
allowedNamespaces: string[]
|
|
||||||
allowedResources: string[]
|
|
||||||
isGlobalWatchEnabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cluster
|
* Cluster
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
import type { PrometheusProvider, PrometheusService } from "./prometheus/provider-registry";
|
import type { PrometheusProvider, PrometheusService } from "./prometheus/provider-registry";
|
||||||
import { PrometheusProviderRegistry } from "./prometheus/provider-registry";
|
import { PrometheusProviderRegistry } from "./prometheus/provider-registry";
|
||||||
import type { ClusterPrometheusPreferences } from "../common/cluster-store";
|
import type { ClusterPrometheusPreferences } from "../common/cluster-types";
|
||||||
import type { Cluster } from "./cluster";
|
import type { Cluster } from "./cluster";
|
||||||
import type httpProxy from "http-proxy";
|
import type httpProxy from "http-proxy";
|
||||||
import url, { UrlWithStringQuery } from "url";
|
import url, { UrlWithStringQuery } from "url";
|
||||||
|
|||||||
@ -23,7 +23,8 @@ import type { IpcMainInvokeEvent } from "electron";
|
|||||||
import { KubernetesCluster } from "../../common/catalog-entities";
|
import { KubernetesCluster } from "../../common/catalog-entities";
|
||||||
import { clusterFrameMap } from "../../common/cluster-frames";
|
import { clusterFrameMap } from "../../common/cluster-frames";
|
||||||
import { clusterActivateHandler, clusterSetFrameIdHandler, clusterVisibilityHandler, clusterRefreshHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterDeleteHandler } from "../../common/cluster-ipc";
|
import { clusterActivateHandler, clusterSetFrameIdHandler, clusterVisibilityHandler, clusterRefreshHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterDeleteHandler } from "../../common/cluster-ipc";
|
||||||
import { ClusterId, ClusterStore } from "../../common/cluster-store";
|
import { ClusterStore } from "../../common/cluster-store";
|
||||||
|
import type { ClusterId } from "../../common/cluster-types";
|
||||||
import { appEventBus } from "../../common/event-bus";
|
import { appEventBus } from "../../common/event-bus";
|
||||||
import { ipcMainHandle } from "../../common/ipc";
|
import { ipcMainHandle } from "../../common/ipc";
|
||||||
import { catalogEntityRegistry } from "../catalog";
|
import { catalogEntityRegistry } from "../catalog";
|
||||||
|
|||||||
@ -22,8 +22,8 @@
|
|||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import type { LensApiRequest } from "../router";
|
import type { LensApiRequest } from "../router";
|
||||||
import { respondJson } from "../utils/http-responses";
|
import { respondJson } from "../utils/http-responses";
|
||||||
import { Cluster, ClusterMetadataKey } from "../cluster";
|
import type { Cluster } from "../cluster";
|
||||||
import type { ClusterPrometheusMetadata } from "../../common/cluster-store";
|
import { ClusterMetadataKey, ClusterPrometheusMetadata } from "../../common/cluster-types";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import { getMetrics } from "../k8s-request";
|
import { getMetrics } from "../k8s-request";
|
||||||
import { PrometheusProviderRegistry } from "../prometheus";
|
import { PrometheusProviderRegistry } from "../prometheus";
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ClusterId } from "../common/cluster-store";
|
import type { ClusterId } from "../common/cluster-types";
|
||||||
import { makeObservable, observable } from "mobx";
|
import { makeObservable, observable } from "mobx";
|
||||||
import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron";
|
import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron";
|
||||||
import windowStateKeeper from "electron-window-state";
|
import windowStateKeeper from "electron-window-state";
|
||||||
|
|||||||
@ -25,9 +25,10 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
import { ClusterModel, ClusterStore } from "../../common/cluster-store";
|
|
||||||
import { loadConfigFromFileSync } from "../../common/kube-helpers";
|
import { loadConfigFromFileSync } from "../../common/kube-helpers";
|
||||||
import { MigrationDeclaration, migrationLog } from "../helpers";
|
import { MigrationDeclaration, migrationLog } from "../helpers";
|
||||||
|
import type { ClusterModel } from "../../common/cluster-types";
|
||||||
|
import { getCustomKubeConfigPath, storedKubeConfigFolder } from "../../common/utils";
|
||||||
|
|
||||||
interface Pre360ClusterModel extends ClusterModel {
|
interface Pre360ClusterModel extends ClusterModel {
|
||||||
kubeConfig: string;
|
kubeConfig: string;
|
||||||
@ -40,7 +41,7 @@ export default {
|
|||||||
const storedClusters: Pre360ClusterModel[] = store.get("clusters") ?? [];
|
const storedClusters: Pre360ClusterModel[] = store.get("clusters") ?? [];
|
||||||
const migratedClusters: ClusterModel[] = [];
|
const migratedClusters: ClusterModel[] = [];
|
||||||
|
|
||||||
fse.ensureDirSync(ClusterStore.storedKubeConfigFolder);
|
fse.ensureDirSync(storedKubeConfigFolder());
|
||||||
|
|
||||||
migrationLog("Number of clusters to migrate: ", storedClusters.length);
|
migrationLog("Number of clusters to migrate: ", storedClusters.length);
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ export default {
|
|||||||
* migrate kubeconfig
|
* migrate kubeconfig
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
const absPath = ClusterStore.getCustomKubeConfigPath(clusterModel.id);
|
const absPath = getCustomKubeConfigPath(clusterModel.id);
|
||||||
|
|
||||||
// take the embedded kubeconfig and dump it into a file
|
// take the embedded kubeconfig and dump it into a file
|
||||||
fse.writeFileSync(absPath, clusterModel.kubeConfig, { encoding: "utf-8", mode: 0o600 });
|
fse.writeFileSync(absPath, clusterModel.kubeConfig, { encoding: "utf-8", mode: 0o600 });
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
import type { ClusterModel } from "../../common/cluster-store";
|
import type { ClusterModel } from "../../common/cluster-types";
|
||||||
import type { MigrationDeclaration } from "../helpers";
|
import type { MigrationDeclaration } from "../helpers";
|
||||||
|
|
||||||
interface Pre500WorkspaceStoreModel {
|
interface Pre500WorkspaceStoreModel {
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ClusterModel, ClusterPreferences, ClusterPrometheusPreferences } from "../../common/cluster-store";
|
import type { ClusterModel, ClusterPreferences, ClusterPrometheusPreferences } from "../../common/cluster-types";
|
||||||
import { MigrationDeclaration, migrationLog } from "../helpers";
|
import { MigrationDeclaration, migrationLog } from "../helpers";
|
||||||
import { generateNewIdFor } from "../utils";
|
import { generateNewIdFor } from "../utils";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
// Fix embedded kubeconfig paths under snap config
|
// Fix embedded kubeconfig paths under snap config
|
||||||
|
|
||||||
import type { ClusterModel } from "../../common/cluster-store";
|
import type { ClusterModel } from "../../common/cluster-types";
|
||||||
import { getAppVersion } from "../../common/utils/app-version";
|
import { getAppVersion } from "../../common/utils/app-version";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { MigrationDeclaration, migrationLog } from "../helpers";
|
import { MigrationDeclaration, migrationLog } from "../helpers";
|
||||||
|
|||||||
@ -23,10 +23,10 @@ import { app } from "electron";
|
|||||||
import { existsSync, readFileSync } from "fs";
|
import { existsSync, readFileSync } from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import { ClusterStore, ClusterStoreModel } from "../../common/cluster-store";
|
import type { ClusterStoreModel } from "../../common/cluster-store";
|
||||||
import type { KubeconfigSyncEntry, UserPreferencesModel } from "../../common/user-store";
|
import type { KubeconfigSyncEntry, UserPreferencesModel } from "../../common/user-store";
|
||||||
import { MigrationDeclaration, migrationLog } from "../helpers";
|
import { MigrationDeclaration, migrationLog } from "../helpers";
|
||||||
import { isLogicalChildPath } from "../../common/utils";
|
import { isLogicalChildPath, storedKubeConfigFolder } from "../../common/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
version: "5.0.3-beta.1",
|
version: "5.0.3-beta.1",
|
||||||
@ -42,8 +42,8 @@ export default {
|
|||||||
for (const cluster of clusters) {
|
for (const cluster of clusters) {
|
||||||
const dirOfKubeconfig = path.dirname(cluster.kubeConfigPath);
|
const dirOfKubeconfig = path.dirname(cluster.kubeConfigPath);
|
||||||
|
|
||||||
if (dirOfKubeconfig === ClusterStore.storedKubeConfigFolder) {
|
if (dirOfKubeconfig === storedKubeConfigFolder()) {
|
||||||
migrationLog(`Skipping ${cluster.id} because kubeConfigPath is under ClusterStore.storedKubeConfigFolder`);
|
migrationLog(`Skipping ${cluster.id} because kubeConfigPath is under the stored KubeConfig folder`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,12 +30,11 @@ import path from "path";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { catalogURL } from "../../../common/routes";
|
import { catalogURL } from "../../../common/routes";
|
||||||
import { ClusterStore } from "../../../common/cluster-store";
|
|
||||||
import { appEventBus } from "../../../common/event-bus";
|
import { appEventBus } from "../../../common/event-bus";
|
||||||
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
|
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
|
||||||
import { docsUrl } from "../../../common/vars";
|
import { docsUrl } from "../../../common/vars";
|
||||||
import { navigate } from "../../navigation";
|
import { navigate } from "../../navigation";
|
||||||
import { iter } from "../../utils";
|
import { getCustomKubeConfigPath, iter } from "../../utils";
|
||||||
import { AceEditor } from "../ace-editor";
|
import { AceEditor } from "../ace-editor";
|
||||||
import { Button } from "../button";
|
import { Button } from "../button";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
@ -93,7 +92,7 @@ export class AddCluster extends React.Component {
|
|||||||
appEventBus.emit({ name: "cluster-add", action: "click" });
|
appEventBus.emit({ name: "cluster-add", action: "click" });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const absPath = ClusterStore.getCustomKubeConfigPath();
|
const absPath = getCustomKubeConfigPath();
|
||||||
|
|
||||||
await fse.ensureDir(path.dirname(absPath));
|
await fse.ensureDir(path.dirname(absPath));
|
||||||
await fse.writeFile(absPath, this.customConfig.trim(), { encoding: "utf-8", mode: 0o600 });
|
await fse.writeFile(absPath, this.customConfig.trim(), { encoding: "utf-8", mode: 0o600 });
|
||||||
|
|||||||
@ -26,8 +26,7 @@ import { reaction } from "mobx";
|
|||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { nodesStore } from "../+nodes/nodes.store";
|
import { nodesStore } from "../+nodes/nodes.store";
|
||||||
import { podsStore } from "../+workloads-pods/pods.store";
|
import { podsStore } from "../+workloads-pods/pods.store";
|
||||||
import { getHostedCluster } from "../../../common/cluster-store";
|
import { getHostedClusterId, interval } from "../../utils";
|
||||||
import { interval } from "../../utils";
|
|
||||||
import { TabLayout } from "../layout/tab-layout";
|
import { TabLayout } from "../layout/tab-layout";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import { ClusterIssues } from "./cluster-issues";
|
import { ClusterIssues } from "./cluster-issues";
|
||||||
@ -35,14 +34,19 @@ import { ClusterMetrics } from "./cluster-metrics";
|
|||||||
import { clusterOverviewStore } from "./cluster-overview.store";
|
import { clusterOverviewStore } from "./cluster-overview.store";
|
||||||
import { ClusterPieCharts } from "./cluster-pie-charts";
|
import { ClusterPieCharts } from "./cluster-pie-charts";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
|
import { ClusterStore } from "../../../common/cluster-store";
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ClusterOverview extends React.Component {
|
export class ClusterOverview extends React.Component {
|
||||||
private metricPoller = interval(60, () => this.loadMetrics());
|
private metricPoller = interval(60, () => this.loadMetrics());
|
||||||
|
|
||||||
loadMetrics() {
|
loadMetrics() {
|
||||||
getHostedCluster().available && clusterOverviewStore.loadMetrics();
|
const cluster = ClusterStore.getInstance().getById(getHostedClusterId());
|
||||||
|
|
||||||
|
if (cluster.available) {
|
||||||
|
clusterOverviewStore.loadMetrics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|||||||
@ -35,7 +35,7 @@ import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
|||||||
import { limitRangeStore } from "../+config-limit-ranges/limit-ranges.store";
|
import { limitRangeStore } from "../+config-limit-ranges/limit-ranges.store";
|
||||||
import { ResourceMetrics } from "../resource-metrics";
|
import { ResourceMetrics } from "../resource-metrics";
|
||||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<Namespace> {
|
interface Props extends KubeObjectDetailsProps<Namespace> {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import { IngressCharts } from "./ingress-charts";
|
|||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { getBackendServiceNamePort, getMetricsForIngress, IIngressMetrics } from "../../api/endpoints/ingress.api";
|
import { getBackendServiceNamePort, getMetricsForIngress, IIngressMetrics } from "../../api/endpoints/ingress.api";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<Ingress> {
|
interface Props extends KubeObjectDetailsProps<Ingress> {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import { makeObservable, observable, reaction } from "mobx";
|
|||||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { NodeDetailsResources } from "./node-details-resources";
|
import { NodeDetailsResources } from "./node-details-resources";
|
||||||
import { DrawerTitle } from "../drawer/drawer-title";
|
import { DrawerTitle } from "../drawer/drawer-title";
|
||||||
import { boundMethod } from "../../utils";
|
import { boundMethod } from "../../utils";
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import { VolumeClaimDiskChart } from "./volume-claim-disk-chart";
|
|||||||
import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object";
|
import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object";
|
||||||
import { getMetricsForPvc, IPvcMetrics, PersistentVolumeClaim } from "../../api/endpoints";
|
import { getMetricsForPvc, IPvcMetrics, PersistentVolumeClaim } from "../../api/endpoints";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<PersistentVolumeClaim> {
|
interface Props extends KubeObjectDetailsProps<PersistentVolumeClaim> {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@ import { makeObservable, observable, reaction } from "mobx";
|
|||||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { boundMethod } from "../../utils";
|
import { boundMethod } from "../../utils";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<DaemonSet> {
|
interface Props extends KubeObjectDetailsProps<DaemonSet> {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
|||||||
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
|
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
|
||||||
import { DeploymentReplicaSets } from "./deployment-replicasets";
|
import { DeploymentReplicaSets } from "./deployment-replicasets";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { boundMethod } from "../../utils";
|
import { boundMethod } from "../../utils";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<Deployment> {
|
interface Props extends KubeObjectDetailsProps<Deployment> {
|
||||||
|
|||||||
@ -39,7 +39,7 @@ import { lookupApiLink } from "../../api/kube-api";
|
|||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { makeObservable, observable } from "mobx";
|
import { makeObservable, observable } from "mobx";
|
||||||
import { podMetricTabs, PodCharts } from "../+workloads-pods/pod-charts";
|
import { podMetricTabs, PodCharts } from "../+workloads-pods/pod-charts";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ResourceMetrics } from "../resource-metrics";
|
import { ResourceMetrics } from "../resource-metrics";
|
||||||
import { boundMethod } from "autobind-decorator";
|
import { boundMethod } from "autobind-decorator";
|
||||||
|
|||||||
@ -34,7 +34,7 @@ import type { IMetrics } from "../../api/endpoints/metrics.api";
|
|||||||
import { ContainerCharts } from "./container-charts";
|
import { ContainerCharts } from "./container-charts";
|
||||||
import { LocaleDate } from "../locale-date";
|
import { LocaleDate } from "../locale-date";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
pod: Pod;
|
pod: Pod;
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import { getItemMetrics } from "../../api/endpoints/metrics.api";
|
|||||||
import { PodCharts, podMetricTabs } from "./pod-charts";
|
import { PodCharts, podMetricTabs } from "./pod-charts";
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<Pod> {
|
interface Props extends KubeObjectDetailsProps<Pod> {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
|||||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { boundMethod } from "../../utils";
|
import { boundMethod } from "../../utils";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<ReplicaSet> {
|
interface Props extends KubeObjectDetailsProps<ReplicaSet> {
|
||||||
|
|||||||
@ -38,7 +38,7 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
|||||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||||
import { ClusterMetricsResourceType } from "../../../main/cluster";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { boundMethod } from "../../utils";
|
import { boundMethod } from "../../utils";
|
||||||
|
|
||||||
interface Props extends KubeObjectDetailsProps<StatefulSet> {
|
interface Props extends KubeObjectDetailsProps<StatefulSet> {
|
||||||
|
|||||||
@ -32,7 +32,6 @@ import { DeploymentScaleDialog } from "./+workloads-deployments/deployment-scale
|
|||||||
import { CronJobTriggerDialog } from "./+workloads-cronjobs/cronjob-trigger-dialog";
|
import { CronJobTriggerDialog } from "./+workloads-cronjobs/cronjob-trigger-dialog";
|
||||||
import { CustomResources } from "./+custom-resources/custom-resources";
|
import { CustomResources } from "./+custom-resources/custom-resources";
|
||||||
import { isAllowedResource } from "../../common/rbac";
|
import { isAllowedResource } from "../../common/rbac";
|
||||||
import { getHostedCluster, getHostedClusterId } from "../../common/cluster-store";
|
|
||||||
import logger from "../../main/logger";
|
import logger from "../../main/logger";
|
||||||
import { webFrame } from "electron";
|
import { webFrame } from "electron";
|
||||||
import { ClusterPageRegistry, getExtensionPageUrl } from "../../extensions/registries/page-registry";
|
import { ClusterPageRegistry, getExtensionPageUrl } from "../../extensions/registries/page-registry";
|
||||||
@ -70,9 +69,14 @@ import { Workloads } from "./+workloads";
|
|||||||
import { Config } from "./+config";
|
import { Config } from "./+config";
|
||||||
import { Storage } from "./+storage";
|
import { Storage } from "./+storage";
|
||||||
import { catalogEntityRegistry } from "../api/catalog-entity-registry";
|
import { catalogEntityRegistry } from "../api/catalog-entity-registry";
|
||||||
|
import { getHostedClusterId } from "../utils";
|
||||||
|
import { ClusterStore } from "../../common/cluster-store";
|
||||||
|
import type { ClusterId } from "../../common/cluster-types";
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class App extends React.Component {
|
export class App extends React.Component {
|
||||||
|
static clusterId: ClusterId;
|
||||||
|
|
||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
@ -81,15 +85,18 @@ export class App extends React.Component {
|
|||||||
static async init() {
|
static async init() {
|
||||||
catalogEntityRegistry.init();
|
catalogEntityRegistry.init();
|
||||||
const frameId = webFrame.routingId;
|
const frameId = webFrame.routingId;
|
||||||
const clusterId = getHostedClusterId();
|
|
||||||
|
|
||||||
logger.info(`[APP]: Init dashboard, clusterId=${clusterId}, frameId=${frameId}`);
|
App.clusterId = getHostedClusterId();
|
||||||
|
|
||||||
|
logger.info(`[APP]: Init dashboard, clusterId=${App.clusterId}, frameId=${frameId}`);
|
||||||
await Terminal.preloadFonts();
|
await Terminal.preloadFonts();
|
||||||
|
await requestMain(clusterSetFrameIdHandler, App.clusterId);
|
||||||
|
|
||||||
await requestMain(clusterSetFrameIdHandler, clusterId);
|
const cluster = ClusterStore.getInstance().getById(App.clusterId);
|
||||||
await getHostedCluster().whenReady; // cluster.activate() is done at this point
|
|
||||||
|
|
||||||
const activeEntityDisposer = reaction(() => catalogEntityRegistry.getById(clusterId), (entity) => {
|
await cluster.whenReady; // cluster.activate() is done at this point
|
||||||
|
|
||||||
|
const activeEntityDisposer = reaction(() => catalogEntityRegistry.getById(App.clusterId), (entity) => {
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -103,7 +110,7 @@ export class App extends React.Component {
|
|||||||
name: "cluster",
|
name: "cluster",
|
||||||
action: "open",
|
action: "open",
|
||||||
params: {
|
params: {
|
||||||
clusterId
|
clusterId: App.clusterId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -212,7 +219,7 @@ export class App extends React.Component {
|
|||||||
<StatefulSetScaleDialog/>
|
<StatefulSetScaleDialog/>
|
||||||
<ReplicaSetScaleDialog/>
|
<ReplicaSetScaleDialog/>
|
||||||
<CronJobTriggerDialog/>
|
<CronJobTriggerDialog/>
|
||||||
<CommandContainer clusterId={getHostedCluster()?.id}/>
|
<CommandContainer clusterId={App.clusterId}/>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import { computed, observable, makeObservable } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { clusterActivateHandler } from "../../../common/cluster-ipc";
|
import { clusterActivateHandler } from "../../../common/cluster-ipc";
|
||||||
import { ClusterId, ClusterStore } from "../../../common/cluster-store";
|
import { ClusterStore } from "../../../common/cluster-store";
|
||||||
import { ipcRendererOn, requestMain } from "../../../common/ipc";
|
import { ipcRendererOn, requestMain } from "../../../common/ipc";
|
||||||
import type { Cluster } from "../../../main/cluster";
|
import type { Cluster } from "../../../main/cluster";
|
||||||
import { cssNames, IClassName } from "../../utils";
|
import { cssNames, IClassName } from "../../utils";
|
||||||
@ -36,6 +36,7 @@ import { Spinner } from "../spinner";
|
|||||||
import type { KubeAuthProxyLog } from "../../../main/kube-auth-proxy";
|
import type { KubeAuthProxyLog } from "../../../main/kube-auth-proxy";
|
||||||
import { navigate } from "../../navigation";
|
import { navigate } from "../../navigation";
|
||||||
import { entitySettingsURL } from "../../../common/routes";
|
import { entitySettingsURL } from "../../../common/routes";
|
||||||
|
import type { ClusterId } from "../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: IClassName;
|
className?: IClassName;
|
||||||
|
|||||||
@ -20,10 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { observable, when } from "mobx";
|
import { observable, when } from "mobx";
|
||||||
import { ClusterId, ClusterStore, getClusterFrameUrl } from "../../../common/cluster-store";
|
|
||||||
import logger from "../../../main/logger";
|
import logger from "../../../main/logger";
|
||||||
import { requestMain } from "../../../common/ipc";
|
import { requestMain } from "../../../common/ipc";
|
||||||
import { clusterVisibilityHandler } from "../../../common/cluster-ipc";
|
import { clusterVisibilityHandler } from "../../../common/cluster-ipc";
|
||||||
|
import { ClusterStore } from "../../../common/cluster-store";
|
||||||
|
import type { ClusterId } from "../../../common/cluster-types";
|
||||||
|
import { getClusterFrameUrl } from "../../utils";
|
||||||
|
|
||||||
export interface LensView {
|
export interface LensView {
|
||||||
isLoaded?: boolean
|
isLoaded?: boolean
|
||||||
|
|||||||
@ -25,8 +25,9 @@ import { Select, SelectOption } from "../../select/select";
|
|||||||
import { Icon } from "../../icon/icon";
|
import { Icon } from "../../icon/icon";
|
||||||
import { Button } from "../../button/button";
|
import { Button } from "../../button/button";
|
||||||
import { SubTitle } from "../../layout/sub-title";
|
import { SubTitle } from "../../layout/sub-title";
|
||||||
import { Cluster, ClusterMetricsResourceType } from "../../../../main/cluster";
|
import type { Cluster } from "../../../../main/cluster";
|
||||||
import { observable, reaction, makeObservable } from "mobx";
|
import { observable, reaction, makeObservable } from "mobx";
|
||||||
|
import { ClusterMetricsResourceType } from "../../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
cluster: Cluster;
|
cluster: Cluster;
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import React from "react";
|
|||||||
import { Input } from "../../input/input";
|
import { Input } from "../../input/input";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { Icon } from "../../icon/icon";
|
import { Icon } from "../../icon/icon";
|
||||||
import { initialNodeShellImage } from "../../../../common/cluster-store";
|
import { initialNodeShellImage } from "../../../../common/cluster-types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
cluster: Cluster;
|
cluster: Cluster;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import { Dialog } from "../dialog";
|
|||||||
import { EventEmitter } from "../../../common/event-emitter";
|
import { EventEmitter } from "../../../common/event-emitter";
|
||||||
import { ipcRendererOn } from "../../../common/ipc";
|
import { ipcRendererOn } from "../../../common/ipc";
|
||||||
import { CommandDialog } from "./command-dialog";
|
import { CommandDialog } from "./command-dialog";
|
||||||
import type { ClusterId } from "../../../common/cluster-store";
|
import type { ClusterId } from "../../../common/cluster-types";
|
||||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||||
import { CommandRegistration, CommandRegistry } from "../../../extensions/registries/command-registry";
|
import { CommandRegistration, CommandRegistry } from "../../../extensions/registries/command-registry";
|
||||||
|
|
||||||
|
|||||||
@ -19,8 +19,9 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ClusterStore } from "../../common/cluster-store";
|
||||||
import type { Cluster } from "../../main/cluster";
|
import type { Cluster } from "../../main/cluster";
|
||||||
import { getHostedCluster } from "../../common/cluster-store";
|
import { getHostedClusterId } from "../utils";
|
||||||
import { namespaceStore } from "./+namespaces/namespace.store";
|
import { namespaceStore } from "./+namespaces/namespace.store";
|
||||||
|
|
||||||
export interface ClusterContext {
|
export interface ClusterContext {
|
||||||
@ -31,7 +32,7 @@ export interface ClusterContext {
|
|||||||
|
|
||||||
export const clusterContext: ClusterContext = {
|
export const clusterContext: ClusterContext = {
|
||||||
get cluster(): Cluster | null {
|
get cluster(): Cluster | null {
|
||||||
return getHostedCluster();
|
return ClusterStore.getInstance().getById(getHostedClusterId());
|
||||||
},
|
},
|
||||||
|
|
||||||
get allNamespaces(): string[] {
|
get allNamespaces(): string[] {
|
||||||
|
|||||||
@ -26,8 +26,9 @@ import { app, remote } from "electron";
|
|||||||
import { comparer, observable, reaction, toJS, when } from "mobx";
|
import { comparer, observable, reaction, toJS, when } from "mobx";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
import { StorageHelper } from "./storageHelper";
|
import { StorageHelper } from "./storageHelper";
|
||||||
import { ClusterStore, getHostedClusterId } from "../../common/cluster-store";
|
import { ClusterStore } from "../../common/cluster-store";
|
||||||
import logger from "../../main/logger";
|
import logger from "../../main/logger";
|
||||||
|
import { getHostedClusterId } from "../../common/utils";
|
||||||
|
|
||||||
const storage = observable({
|
const storage = observable({
|
||||||
initialized: false,
|
initialized: false,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user