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

detach namespace-store from kube-watch-api.ts, preload all namespaces by default with store.loadAll

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-01-27 18:29:32 +02:00
parent 78260278c0
commit 70daac0074
19 changed files with 63 additions and 66 deletions

View File

@ -5,10 +5,9 @@ import type { Cluster } from "../../main/cluster";
import type { IKubeWatchEvent, IKubeWatchEventStreamEnd, IWatchRoutePayload } from "../../main/routes/watch-route";
import type { KubeObject } from "./kube-object";
import type { KubeObjectStore } from "../kube-object.store";
import type { NamespaceStore } from "../components/+namespaces/namespace.store";
import debounce from "lodash/debounce";
import { comparer, computed, observable, reaction } from "mobx";
import { comparer, computed, observable, reaction, when } from "mobx";
import { autobind, EventEmitter } from "../utils";
import { ensureObjectSelfLink, KubeApi, parseKubeApi } from "./kube-api";
import { KubeJsonApiData, KubeJsonApiError } from "./kube-json-api";
@ -41,13 +40,13 @@ export interface IKubeWatchLog {
@autobind()
export class KubeWatchApi {
private cluster: Cluster;
private namespaceStore: NamespaceStore;
private requestId = 0;
private isConnected = false;
private reader: ReadableStreamReader<string>;
private subscribers = observable.map<KubeApi, number>();
@observable.ref private getCluster: () => Cluster;
@observable.ref private getNamespaces: () => string[];
@observable isConnected = false;
@observable subscribers = observable.map<KubeApi, number>();
// events
public onMessage = new EventEmitter<[IKubeWatchMessage]>();
@ -57,16 +56,13 @@ export class KubeWatchApi {
}
@computed get apis(): string[] {
const { cluster, namespaceStore } = this;
const activeApis = Array.from(this.subscribers.keys());
return activeApis.map(api => {
if (!cluster.isAllowedResource(api.kind)) {
return Array.from(this.subscribers.keys()).map(api => {
if (!this.getCluster?.().isAllowedResource(api.kind)) {
return [];
}
if (api.isNamespaced) {
return namespaceStore.getContextNamespaces().map(namespace => api.getWatchUrl(namespace));
return this.getNamespaces().map(namespace => api.getWatchUrl(namespace));
} else {
return api.getWatchUrl();
}
@ -77,14 +73,16 @@ export class KubeWatchApi {
this.init();
}
setupCluster(getter: () => Cluster) {
this.getCluster = getter;
}
setupWatchingNamespaces(getter: () => string[]) {
this.getNamespaces = getter;
}
private async init() {
const { getHostedCluster } = await import("../../common/cluster-store");
const { namespaceStore } = await import("../components/+namespaces/namespace.store");
await namespaceStore.whenReady;
this.cluster = getHostedCluster();
this.namespaceStore = namespaceStore;
await when(() => Boolean(this.getCluster && this.getNamespaces));
this.bindAutoConnect();
}
@ -143,7 +141,7 @@ export class KubeWatchApi {
}
if (preload) {
loading.push(...stores.map(store => store.loadAll()));
loading.push(...stores.map(store => store.loadAll(this.getNamespaces())));
}
if (waitUntilLoaded) {

View File

@ -58,11 +58,11 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
}
@action
async loadAll() {
async loadAll(namespaces = namespaceStore.allowedNamespaces) {
this.isLoading = true;
try {
const items = await this.loadItems(namespaceStore.getContextNamespaces());
const items = await this.loadItems(namespaces);
this.items.replace(this.sortItems(items));
this.isLoaded = true;
@ -73,6 +73,10 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
}
}
async loadSelectedNamespaces(): Promise<void> {
return this.loadAll(namespaceStore.getContextNamespaces());
}
async loadItems(namespaces: string[]) {
return Promise
.all(namespaces.map(namespace => helmReleasesApi.list(namespace)))
@ -82,7 +86,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
async create(payload: IReleaseCreatePayload) {
const response = await helmReleasesApi.create(payload);
if (this.isLoaded) this.loadAll();
if (this.isLoaded) this.loadSelectedNamespaces();
return response;
}
@ -90,7 +94,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
async update(name: string, namespace: string, payload: IReleaseUpdatePayload) {
const response = await helmReleasesApi.update(name, namespace, payload);
if (this.isLoaded) this.loadAll();
if (this.isLoaded) this.loadSelectedNamespaces();
return response;
}
@ -98,7 +102,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
async rollback(name: string, namespace: string, revision: number) {
const response = await helmReleasesApi.rollback(name, namespace, revision);
if (this.isLoaded) this.loadAll();
if (this.isLoaded) this.loadSelectedNamespaces();
return response;
}

View File

@ -30,7 +30,7 @@ export class CrdResources extends React.Component<Props> {
const { store } = this;
if (store && !store.isLoading && !store.isLoaded) {
store.loadAll();
store.loadSelectedNamespaces();
}
})
]);

View File

@ -14,7 +14,7 @@ export interface KubeEventDetailsProps {
@observer
export class KubeEventDetails extends React.Component<KubeEventDetailsProps> {
async componentDidMount() {
eventStore.loadAll();
eventStore.loadSelectedNamespaces();
}
render() {

View File

@ -32,8 +32,8 @@ export class NamespaceDetails extends React.Component<Props> {
}
componentDidMount() {
resourceQuotaStore.loadAll();
limitRangeStore.loadAll();
resourceQuotaStore.loadSelectedNamespaces();
limitRangeStore.loadSelectedNamespaces();
}
render() {

View File

@ -73,7 +73,7 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
}
private autoLoadAllowedNamespaces(): IReactionDisposer {
return reaction(() => this.allowedNamespaces, () => this.loadAll(), {
return reaction(() => this.allowedNamespaces, namespaces => this.loadAll(namespaces), {
fireImmediately: true,
equals: comparer.shallow,
});

View File

@ -29,9 +29,7 @@ export class NodeDetails extends React.Component<Props> {
});
async componentDidMount() {
if (!podsStore.isLoaded) {
podsStore.loadAll();
}
podsStore.loadSelectedNamespaces();
}
componentWillUnmount() {

View File

@ -80,7 +80,7 @@ export class AddRoleBindingDialog extends React.Component<Props> {
];
this.isLoading = true;
await Promise.all(stores.map(store => store.loadAll()));
await Promise.all(stores.map(store => store.loadSelectedNamespaces()));
this.isLoading = false;
}

View File

@ -20,9 +20,7 @@ interface Props extends KubeObjectDetailsProps<CronJob> {
@observer
export class CronJobDetails extends React.Component<Props> {
async componentDidMount() {
if (!jobStore.isLoaded) {
jobStore.loadAll();
}
jobStore.loadSelectedNamespaces();
}
render() {

View File

@ -30,9 +30,7 @@ export class DaemonSetDetails extends React.Component<Props> {
});
componentDidMount() {
if (!podsStore.isLoaded) {
podsStore.loadAll();
}
podsStore.loadSelectedNamespaces();
}
componentWillUnmount() {

View File

@ -31,9 +31,7 @@ export class DeploymentDetails extends React.Component<Props> {
});
componentDidMount() {
if (!podsStore.isLoaded) {
podsStore.loadAll();
}
podsStore.loadSelectedNamespaces();
}
componentWillUnmount() {

View File

@ -25,9 +25,7 @@ interface Props extends KubeObjectDetailsProps<Job> {
@observer
export class JobDetails extends React.Component<Props> {
async componentDidMount() {
if (!podsStore.isLoaded) {
podsStore.loadAll();
}
podsStore.loadSelectedNamespaces();
}
render() {

View File

@ -29,9 +29,7 @@ export class ReplicaSetDetails extends React.Component<Props> {
});
async componentDidMount() {
if (!podsStore.isLoaded) {
podsStore.loadAll();
}
podsStore.loadSelectedNamespaces();
}
componentWillUnmount() {

View File

@ -30,9 +30,7 @@ export class StatefulSetDetails extends React.Component<Props> {
});
componentDidMount() {
if (!podsStore.isLoaded) {
podsStore.loadAll();
}
podsStore.loadSelectedNamespaces();
}
componentWillUnmount() {

View File

@ -1,4 +1,5 @@
import React from "react";
import { computed, observable, reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import { Redirect, Route, Router, Switch } from "react-router";
import { history } from "../navigation";
@ -41,12 +42,12 @@ import { clusterSetFrameIdHandler } from "../../common/cluster-ipc";
import { ClusterPageMenuRegistration, clusterPageMenuRegistry } from "../../extensions/registries";
import { TabLayout, TabLayoutRoute } from "./layout/tab-layout";
import { StatefulSetScaleDialog } from "./+workloads-statefulsets/statefulset-scale-dialog";
import { ReplicaSetScaleDialog } from "./+workloads-replicasets/replicaset-scale-dialog";
import { eventStore } from "./+events/event.store";
import { computed, reaction, observable } from "mobx";
import { nodesStore } from "./+nodes/nodes.store";
import { podsStore } from "./+workloads-pods/pods.store";
import { namespaceStore } from "./+namespaces/namespace.store";
import { kubeWatchApi } from "../api/kube-watch-api";
import { ReplicaSetScaleDialog } from "./+workloads-replicasets/replicaset-scale-dialog";
@observer
export class App extends React.Component {
@ -76,6 +77,9 @@ export class App extends React.Component {
}
componentDidMount() {
kubeWatchApi.setupCluster(getHostedCluster);
kubeWatchApi.setupWatchingNamespaces(namespaceStore.getContextNamespaces);
disposeOnUnmount(this, [
kubeWatchApi.subscribeStores([podsStore, nodesStore, eventStore], {
preload: true,
@ -155,9 +159,9 @@ export class App extends React.Component {
const tabRoutes = this.getTabLayoutRoutes(menu);
if (tabRoutes.length > 0) {
const pageComponent = () => <TabLayout tabs={tabRoutes} />;
const pageComponent = () => <TabLayout tabs={tabRoutes}/>;
route = <Route key={`extension-tab-layout-route-${index}`} component={pageComponent} path={tabRoutes.map((tab) => tab.routePath)} />;
route = <Route key={`extension-tab-layout-route-${index}`} component={pageComponent} path={tabRoutes.map((tab) => tab.routePath)}/>;
this.extensionRoutes.set(menu, route);
} else {
const page = clusterPageRegistry.getByPageTarget(menu.target);

View File

@ -80,7 +80,7 @@ export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
const values = this.values.getData(tabId);
await Promise.all([
!releaseStore.isLoaded && releaseStore.loadAll(),
!releaseStore.isLoaded && releaseStore.loadSelectedNamespaces(),
!values && this.loadValues(tabId)
]);
}

View File

@ -138,7 +138,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
const { store, dependentStores } = this.props;
const stores = Array.from(new Set([store, ...dependentStores]));
stores.forEach(store => store.loadAll());
stores.forEach(store => store.loadAll(namespaceStore.getContextNamespaces()));
}
private filterCallbacks: { [type: string]: ItemsFilter } = {

View File

@ -40,9 +40,7 @@ interface Props {
@observer
export class Sidebar extends React.Component<Props> {
async componentDidMount() {
if (!crdStore.isLoaded && isAllowedResource("customresourcedefinitions")) {
crdStore.loadAll();
}
crdStore.loadSelectedNamespaces();
}
renderCustomResources() {

View File

@ -106,17 +106,18 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
}
@action
async loadAll({ namespaces: contextNamespaces }: { namespaces?: string[] } = {}) {
async loadAll(namespaces: string[] = []): Promise<void> {
this.isLoading = true;
try {
if (!contextNamespaces) {
if (!namespaces.length) {
const { namespaceStore } = await import("./components/+namespaces/namespace.store");
contextNamespaces = namespaceStore.getContextNamespaces();
// load all available namespaces by default
namespaces.push(...namespaceStore.allowedNamespaces);
}
let items = await this.loadItems({ namespaces: contextNamespaces, api: this.api });
let items = await this.loadItems({ namespaces, api: this.api });
items = this.filterItemsOnLoad(items);
items = this.sortItems(items);
@ -131,6 +132,12 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
}
}
async loadSelectedNamespaces(): Promise<void> {
const { namespaceStore } = await import("./components/+namespaces/namespace.store");
return this.loadAll(namespaceStore.getContextNamespaces());
}
protected resetOnError(error: any) {
if (error) this.reset();
}