Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ban circular dependencies #2822

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 18 additions & 1 deletion .eslintrc.js
Expand Up @@ -39,6 +39,7 @@ module.exports = {
],
extends: [
"eslint:recommended",
"plugin:import/recommended",
],
env: {
node: true
Expand All @@ -53,6 +54,7 @@ module.exports = {
],
rules: {
"header/header": [2, "./license-header"],
// "import/no-cycle": 2,
"indent": ["error", 2, {
"SwitchCase": 1,
}],
Expand Down Expand Up @@ -93,6 +95,8 @@ module.exports = {
parser: "@typescript-eslint/parser",
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
],
plugins: [
"header",
Expand All @@ -104,6 +108,7 @@ module.exports = {
},
rules: {
"header/header": [2, "./license-header"],
// "import/no-cycle": 2,
"no-invalid-this": "off",
"@typescript-eslint/no-invalid-this": ["error"],
"@typescript-eslint/explicit-function-return-type": "off",
Expand Down Expand Up @@ -158,6 +163,8 @@ module.exports = {
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
],
parserOptions: {
ecmaVersion: 2018,
Expand All @@ -166,6 +173,7 @@ module.exports = {
},
rules: {
"header/header": [2, "./license-header"],
// "import/no-cycle": 2,
"no-invalid-this": "off",
"@typescript-eslint/no-invalid-this": ["error"],
"@typescript-eslint/explicit-function-return-type": "off",
Expand Down Expand Up @@ -212,6 +220,15 @@ module.exports = {
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]},
]
},
}
},
{
files: [
"extensions/**/*.ts",
"extensions/**/*.tsx",
],
rules: {
"import/no-unresolved": "off", // warns on @k8slens/extensions
}
},
]
};
6 changes: 3 additions & 3 deletions extensions/kube-object-event-status/src/resolver.tsx
Expand Up @@ -22,7 +22,7 @@
import { K8sApi } from "@k8slens/extensions";

export function resolveStatus(object: K8sApi.KubeObject): K8sApi.KubeObjectStatus {
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi);
const eventStore = K8sApi.ApiManager.getInstance().getStore(K8sApi.eventApi);
const events = (eventStore as K8sApi.EventStore).getEventsByObject(object);
const warnings = events.filter(evt => evt.isWarning());

Expand All @@ -42,7 +42,7 @@ export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus {
if (!pod.hasIssues()) {
return null;
}
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi);
const eventStore = K8sApi.ApiManager.getInstance().getStore(K8sApi.eventApi);
const events = (eventStore as K8sApi.EventStore).getEventsByObject(pod);
const warnings = events.filter(evt => evt.isWarning());

Expand All @@ -59,7 +59,7 @@ export function resolveStatusForPods(pod: K8sApi.Pod): K8sApi.KubeObjectStatus {
}

export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeObjectStatus {
const eventStore = K8sApi.apiManager.getStore(K8sApi.eventApi);
const eventStore = K8sApi.ApiManager.getInstance().getStore(K8sApi.eventApi);
let events = (eventStore as K8sApi.EventStore).getEventsByObject(cronJob);
const warnings = events.filter(evt => evt.isWarning());

Expand Down
2 changes: 1 addition & 1 deletion integration/__tests__/command-palette.tests.ts
Expand Up @@ -40,7 +40,7 @@ describe("Lens command palette", () => {

it("opens command dialog from menu", async () => {
await app.electron.ipcRenderer.send("test-menu-item-click", "View", "Command Palette...");
await app.client.waitUntilTextExists(".Select__option", "Preferences: Open");
await app.client.waitUntilTextExists(".Select__option", "Hotbar: Switch");
await app.client.keys("Escape");
});
});
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -315,6 +315,7 @@
"electron-notarize": "^0.3.0",
"eslint": "^7.7.0",
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-import": "^2.23.2",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-unused-imports": "^1.0.1",
"file-loader": "^6.0.0",
Expand Down
Empty file removed src/common/.gitkeep
Empty file.
12 changes: 7 additions & 5 deletions src/common/__tests__/cluster-store.test.ts
Expand Up @@ -23,9 +23,11 @@ import fs from "fs";
import mockFs from "mock-fs";
import yaml from "js-yaml";
import { Cluster } from "../../main/cluster";
import { ClusterStore, getClusterIdFromHost } from "../cluster-store";
import { ClusterStore } from "../cluster-store";
import { Console } from "console";
import { stdout, stderr } from "process";
import { embedCustomKubeConfig } from "../utils";
import { getClusterIdFromHost } from "../cluster-types";

console = new Console(stdout, stderr);

Expand Down Expand Up @@ -102,7 +104,7 @@ describe("empty config", () => {
icon: "data:image/jpeg;base64, iVBORw0KGgoAAAANSUhEUgAAA1wAAAKoCAYAAABjkf5",
clusterName: "minikube"
},
kubeConfigPath: ClusterStore.embedCustomKubeConfig("foo", kubeconfig)
kubeConfigPath: embedCustomKubeConfig("foo", kubeconfig)
})
);
});
Expand Down Expand Up @@ -135,15 +137,15 @@ describe("empty config", () => {
preferences: {
clusterName: "prod"
},
kubeConfigPath: ClusterStore.embedCustomKubeConfig("prod", kubeconfig)
kubeConfigPath: embedCustomKubeConfig("prod", kubeconfig)
}),
new Cluster({
id: "dev",
contextName: "foo2",
preferences: {
clusterName: "dev"
},
kubeConfigPath: ClusterStore.embedCustomKubeConfig("dev", kubeconfig)
kubeConfigPath: embedCustomKubeConfig("dev", kubeconfig)
})
);
});
Expand All @@ -154,7 +156,7 @@ describe("empty config", () => {
});

it("check if cluster's kubeconfig file saved", () => {
const file = ClusterStore.embedCustomKubeConfig("boo", "kubeconfig");
const file = embedCustomKubeConfig("boo", "kubeconfig");

expect(fs.readFileSync(file, "utf8")).toBe("kubeconfig");
});
Expand Down
32 changes: 29 additions & 3 deletions src/common/__tests__/search-store.test.ts
Expand Up @@ -22,6 +22,7 @@
import { SearchStore } from "../search-store";
import { Console } from "console";
import { stdout, stderr } from "process";
import { DockStore } from "../../renderer/components/dock";

jest.mock("electron", () => ({
app: {
Expand All @@ -31,24 +32,33 @@ jest.mock("electron", () => ({

console = new Console(stdout, stderr);

let searchStore: SearchStore = null;
const logs = [
"1:M 30 Oct 2020 16:17:41.553 # Connection with replica 172.17.0.12:6379 lost",
"1:M 30 Oct 2020 16:17:41.623 * Replica 172.17.0.12:6379 asks for synchronization",
"1:M 30 Oct 2020 16:17:41.623 * Starting Partial resynchronization request from 172.17.0.12:6379 accepted. Sending 0 bytes of backlog starting from offset 14407."
];

describe("search store tests", () => {
beforeEach(async () => {
searchStore = new SearchStore();
beforeEach(() => {
DockStore.createInstance();
SearchStore.createInstance();
});

afterEach(() => {
DockStore.resetInstance();
SearchStore.resetInstance();
})

it("does nothing with empty search query", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch([], "");
expect(searchStore.occurrences).toEqual([]);
});

it("doesn't break if no text provided", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(null, "replica");
expect(searchStore.occurrences).toEqual([]);

Expand All @@ -57,33 +67,45 @@ describe("search store tests", () => {
});

it("find 3 occurrences across 3 lines", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "172");
expect(searchStore.occurrences).toEqual([0, 1, 2]);
});

it("find occurrences within 1 line (case-insensitive)", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "Starting");
expect(searchStore.occurrences).toEqual([2, 2]);
});

it("sets overlay index equal to first occurrence", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "Replica");
expect(searchStore.activeOverlayIndex).toBe(0);
});

it("set overlay index to next occurrence", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "172");
searchStore.setNextOverlayActive();
expect(searchStore.activeOverlayIndex).toBe(1);
});

it("sets overlay to last occurrence", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "172");
searchStore.setPrevOverlayActive();
expect(searchStore.activeOverlayIndex).toBe(2);
});

it("gets line index where overlay is located", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "synchronization");
expect(searchStore.activeOverlayLine).toBe(1);
});
Expand All @@ -95,12 +117,16 @@ describe("search store tests", () => {
});

it("gets active find number", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "172");
searchStore.setNextOverlayActive();
expect(searchStore.activeFind).toBe(2);
});

it("gets total finds number", () => {
const searchStore = SearchStore.getInstance();

searchStore.onSearch(logs, "Starting");
expect(searchStore.totalFinds).toBe(2);
});
Expand Down
21 changes: 7 additions & 14 deletions src/common/base-store.ts
Expand Up @@ -22,12 +22,11 @@
import path from "path";
import Config from "conf";
import type { Options as ConfOptions } from "conf/dist/source/types";
import { app, ipcMain, IpcMainEvent, ipcRenderer, IpcRendererEvent, remote } from "electron";
import { app, ipcMain, ipcRenderer, remote } from "electron";
import { IReactionOptions, observable, reaction, runInAction, when } from "mobx";
import Singleton from "./utils/singleton";
import { getAppVersion } from "./utils/app-version";
import { Singleton, getAppVersion } from "./utils";
import logger from "../main/logger";
import { broadcastMessage, subscribeToBroadcast, unsubscribeFromBroadcast } from "./ipc";
import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc";
import isEqual from "lodash/isEqual";

export interface BaseStoreParams<T = any> extends ConfOptions<T> {
Expand Down Expand Up @@ -118,23 +117,17 @@ export abstract class BaseStore<T = any> extends Singleton {
);

if (ipcMain) {
const callback = (event: IpcMainEvent, model: T) => {
this.syncDisposers.push(ipcMainOn(this.syncMainChannel, (event, model: T) => {
logger.silly(`[STORE]: SYNC ${this.name} from renderer`, { model });
this.onSync(model);
};

subscribeToBroadcast(this.syncMainChannel, callback);
this.syncDisposers.push(() => unsubscribeFromBroadcast(this.syncMainChannel, callback));
}));
}

if (ipcRenderer) {
const callback = (event: IpcRendererEvent, model: T) => {
this.syncDisposers.push(ipcRendererOn(this.syncRendererChannel, (event, model: T) => {
logger.silly(`[STORE]: SYNC ${this.name} from main`, { model });
this.onSyncFromMain(model);
};

subscribeToBroadcast(this.syncRendererChannel, callback);
this.syncDisposers.push(() => unsubscribeFromBroadcast(this.syncRendererChannel, callback));
}));
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/common/catalog-entities/kubernetes-cluster.ts
Expand Up @@ -20,15 +20,15 @@
*/

import { catalogCategoryRegistry } from "../catalog/catalog-category-registry";
import { CatalogEntity, CatalogEntityActionContext, CatalogEntityAddMenuContext, CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
import { CatalogEntity, CatalogEntityActionContext, CatalogEntityAddMenuContext, CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus, CatalogCategory, CatalogCategorySpec } from "../catalog";
import { clusterActivateHandler, clusterDisconnectHandler } from "../cluster-ipc";
import { ClusterStore } from "../cluster-store";
import { requestMain } from "../ipc";
import { productName } from "../vars";
import { CatalogCategory, CatalogCategorySpec } from "../catalog";
import { addClusterURL } from "../routes";
import { storedKubeConfigFolder } from "../utils";
import { app } from "electron";


export type KubernetesClusterPrometheusMetrics = {
address?: {
namespace: string;
Expand Down Expand Up @@ -109,7 +109,7 @@ export class KubernetesCluster extends CatalogEntity<CatalogEntityMetadata, Kube
},
];

if (this.metadata.labels["file"]?.startsWith(ClusterStore.storedKubeConfigFolder)) {
if (this.metadata.labels["file"]?.startsWith(storedKubeConfigFolder())) {
context.menuItems.push({
title: "Delete",
onlyVisibleForSource: "local",
Expand Down Expand Up @@ -171,7 +171,7 @@ export class KubernetesClusterCategory extends CatalogCategory {
icon: "text_snippet",
title: "Add from kubeconfig",
onClick: () => {
ctx.navigate("/add-cluster");
ctx.navigate(addClusterURL());
}
});
});
Expand Down