mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
poc
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
77077ef72c
commit
f1360d602d
@ -19,18 +19,21 @@
|
|||||||
* 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 { KubeObjectStore } from "../kube-object.store";
|
import { action, makeObservable, observable } from "mobx";
|
||||||
|
import { autoBind, Singleton } from "../utils";
|
||||||
import { action, observable, makeObservable } from "mobx";
|
import { parseKubeApi } from "./kube-api";
|
||||||
import { autoBind, iter } from "../utils";
|
import type { KubeObjectStoreConstructor, KubeObjectStore } from "../kube-object.store";
|
||||||
import { KubeApi, parseKubeApi } from "./kube-api";
|
import type { KubeApi } from "./kube-api";
|
||||||
|
import type { Cluster } from "../../main/cluster";
|
||||||
import type { KubeObject } from "./kube-object";
|
import type { KubeObject } from "./kube-object";
|
||||||
|
import type { ApiSpecifier } from "./kube-watch-api";
|
||||||
|
|
||||||
export class ApiManager {
|
export class ApiManager extends Singleton {
|
||||||
private apis = observable.map<string, KubeApi<KubeObject>>();
|
private apis = observable.map<string, KubeApi<KubeObject>>();
|
||||||
private stores = observable.map<string, KubeObjectStore<KubeObject>>();
|
private stores = observable.map<string, KubeObjectStore<KubeObject>>();
|
||||||
|
|
||||||
constructor() {
|
constructor(public cluster: Cluster) {
|
||||||
|
super();
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
autoBind(this);
|
autoBind(this);
|
||||||
}
|
}
|
||||||
@ -40,17 +43,17 @@ export class ApiManager {
|
|||||||
return this.apis.get(pathOrCallback) || this.apis.get(parseKubeApi(pathOrCallback).apiBase);
|
return this.apis.get(pathOrCallback) || this.apis.get(parseKubeApi(pathOrCallback).apiBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
return iter.find(this.apis.values(), pathOrCallback ?? (() => true));
|
return Array.from(this.apis.values()).find(pathOrCallback ?? (() => true));
|
||||||
}
|
}
|
||||||
|
|
||||||
getApiByKind(kind: string, apiVersion: string) {
|
getApiByKind(kind: string, apiVersion: string) {
|
||||||
return iter.find(this.apis.values(), api => api.kind === kind && api.apiVersionWithGroup === apiVersion);
|
return Array.from(this.apis.values()).find((api) => api.kind === kind && api.apiVersionWithGroup === apiVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerApi(apiBase: string, api: KubeApi<KubeObject>) {
|
registerApi(apiBase: string, api: KubeApi<KubeObject>) {
|
||||||
if (!this.apis.has(apiBase)) {
|
if (!this.apis.has(apiBase)) {
|
||||||
this.stores.forEach((store) => {
|
this.stores.forEach((store) => {
|
||||||
if (store.api === api) {
|
if(store.api === api) {
|
||||||
this.stores.set(apiBase, store);
|
this.stores.set(apiBase, store);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -59,14 +62,8 @@ export class ApiManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resolveApi<K extends KubeObject>(api?: string | KubeApi<K>): KubeApi<K> | undefined {
|
protected resolveApi(api: string | ApiSpecifier): ApiSpecifier {
|
||||||
if (!api) {
|
if (typeof api === "string") return this.getApi(api);
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof api === "string") {
|
|
||||||
return this.getApi(api) as KubeApi<K>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
@ -82,15 +79,15 @@ export class ApiManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[] = [store.api]) {
|
registerStore<T extends KubeObject>(storeConstructor: KubeObjectStoreConstructor<T>, apis?: KubeApi<KubeObject>[]) {
|
||||||
apis.forEach(api => {
|
const store = new storeConstructor(this.cluster);
|
||||||
|
|
||||||
|
(apis ?? [store.api]).forEach(api => {
|
||||||
this.stores.set(api.apiBase, store);
|
this.stores.set(api.apiBase, store);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getStore<S extends KubeObjectStore<KubeObject>>(api: string | KubeApi<KubeObject>): S | undefined {
|
getStore<S extends KubeObjectStore<KubeObject>>(api: string | ApiSpecifier): S {
|
||||||
return this.stores.get(this.resolveApi(api)?.apiBase) as S;
|
return this.stores.get(this.resolveApi(api)?.apiBase) as S;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const apiManager = new ApiManager();
|
|
||||||
|
|||||||
@ -98,13 +98,14 @@ export interface KubeObjectStatus {
|
|||||||
|
|
||||||
export type KubeMetaField = keyof KubeObjectMetadata;
|
export type KubeMetaField = keyof KubeObjectMetadata;
|
||||||
|
|
||||||
|
export type BaseKubeObject = KubeObject<KubeObjectMetadata, KubeStatus, any>;
|
||||||
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
||||||
static readonly kind: string;
|
static readonly kind: string;
|
||||||
static readonly namespaced: boolean;
|
static readonly namespaced: boolean;
|
||||||
|
|
||||||
apiVersion: string;
|
apiVersion: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
metadata: Metadata;
|
metadata?: Metadata;
|
||||||
status?: Status;
|
status?: Status;
|
||||||
spec?: Spec;
|
spec?: Spec;
|
||||||
managedFields?: any;
|
managedFields?: any;
|
||||||
@ -113,7 +114,7 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
|||||||
return new KubeObject(data);
|
return new KubeObject(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isNonSystem(item: KubeJsonApiData | KubeObject) {
|
static isNonSystem(item: KubeJsonApiData | BaseKubeObject) {
|
||||||
return !item.metadata.name.startsWith("system:");
|
return !item.metadata.name.startsWith("system:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,10 @@ export interface IKubeWatchLog {
|
|||||||
cssStyle?: string;
|
cssStyle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiSpecifier {
|
||||||
|
apiBase: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class KubeWatchApi {
|
export class KubeWatchApi {
|
||||||
@observable context: ClusterContext = null;
|
@observable context: ClusterContext = null;
|
||||||
|
|
||||||
|
|||||||
@ -94,6 +94,8 @@ export class App extends React.Component {
|
|||||||
|
|
||||||
const cluster = ClusterStore.getInstance().getById(App.clusterId);
|
const cluster = ClusterStore.getInstance().getById(App.clusterId);
|
||||||
|
|
||||||
|
ApiManager.createInstance(cluster);
|
||||||
|
|
||||||
await cluster.whenReady; // cluster.activate() is done at this point
|
await cluster.whenReady; // cluster.activate() is done at this point
|
||||||
|
|
||||||
const activeEntityDisposer = reaction(() => catalogEntityRegistry.getById(App.clusterId), (entity) => {
|
const activeEntityDisposer = reaction(() => catalogEntityRegistry.getById(App.clusterId), (entity) => {
|
||||||
|
|||||||
37
src/renderer/components/namespace-helpers.ts
Executable file
37
src/renderer/components/namespace-helpers.ts
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
import type { Cluster } from "../../main/cluster";
|
||||||
|
import { ApiManager } from "../api/api-manager";
|
||||||
|
import { Namespace } from "../api/endpoints";
|
||||||
|
|
||||||
|
export function allNamespaces(cluster: Cluster | null): string[] {
|
||||||
|
if (!cluster) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// user given list of namespaces
|
||||||
|
if (cluster?.accessibleNamespaces.length) {
|
||||||
|
return cluster.accessibleNamespaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
const namespaceStore = ApiManager.getInstance().getStore(Namespace.apiBase);
|
||||||
|
|
||||||
|
if (namespaceStore.items.length > 0) {
|
||||||
|
// namespaces from kubernetes api
|
||||||
|
return namespaceStore.items.map((namespace) => namespace.getName());
|
||||||
|
} else {
|
||||||
|
// fallback to cluster resolved namespaces because we could not load list
|
||||||
|
return cluster.allowedNamespaces || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function contextNamespaces(): string[] {
|
||||||
|
// TODO: will remove when refactoring this sort of thing
|
||||||
|
return (ApiManager.getInstance().getStore(Namespace.apiBase) as any).contextNamespaces ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isLoadingAll(cluster: Cluster, namespaces: string[]): boolean {
|
||||||
|
const allNs = allNamespaces(cluster);
|
||||||
|
|
||||||
|
return allNs.length > 1
|
||||||
|
&& cluster.accessibleNamespaces.length === 0
|
||||||
|
&& allNs.every(ns => namespaces.includes(ns));
|
||||||
|
}
|
||||||
@ -19,53 +19,43 @@
|
|||||||
* 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 { ClusterContext } from "./components/context";
|
|
||||||
|
|
||||||
import { action, computed, makeObservable, observable, reaction, when } from "mobx";
|
import { action, computed, makeObservable, observable, reaction, when } from "mobx";
|
||||||
import { autoBind, noop, rejectPromiseBy } from "./utils";
|
import { autoBind, bifurcateArray, noop, rejectPromiseBy, toJS } from "./utils";
|
||||||
import { KubeObject, KubeStatus } from "./api/kube-object";
|
import { KubeObject, KubeStatus } from "./api/kube-object";
|
||||||
import type { IKubeWatchEvent } from "./api/kube-watch-api";
|
import type { IKubeWatchEvent } from "./api/kube-watch-api";
|
||||||
import { ItemStore } from "./item.store";
|
import { ItemStore } from "./item.store";
|
||||||
import { apiManager } from "./api/api-manager";
|
import { ApiManager } from "./api/api-manager";
|
||||||
import { ensureObjectSelfLink, IKubeApiQueryParams, KubeApi, parseKubeApi } from "./api/kube-api";
|
import { IKubeApiQueryParams, KubeApi, parseKubeApi } from "./api/kube-api";
|
||||||
import type { KubeJsonApiData } from "./api/kube-json-api";
|
import type { KubeJsonApiData } from "./api/kube-json-api";
|
||||||
import { Notifications } from "./components/notifications";
|
import { Notifications } from "./components/notifications";
|
||||||
|
import { allNamespaces, contextNamespaces, isLoadingAll } from "./components/namespace-helpers";
|
||||||
|
import type { Cluster } from "../main/cluster";
|
||||||
|
|
||||||
export interface KubeObjectStoreLoadingParams<K extends KubeObject> {
|
export interface KubeObjectStoreLoadingParams<T extends KubeObject> {
|
||||||
namespaces: string[];
|
namespaces: string[];
|
||||||
api?: KubeApi<K>;
|
api?: KubeApi<T>;
|
||||||
reqInit?: RequestInit;
|
reqInit?: RequestInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T> {
|
export type KubeObjectStoreConstructor<T extends KubeObject> = new (cluster: Cluster) => KubeObjectStore<T>;
|
||||||
static defaultContext = observable.box<ClusterContext>(); // TODO: support multiple cluster contexts
|
|
||||||
|
|
||||||
|
export abstract class KubeObjectStore<T extends KubeObject = KubeObject> extends ItemStore<T> {
|
||||||
abstract api: KubeApi<T>;
|
abstract api: KubeApi<T>;
|
||||||
public readonly limit?: number;
|
public readonly limit?: number;
|
||||||
public readonly bufferSize: number = 50000;
|
public readonly bufferSize: number = 50000;
|
||||||
@observable private loadedNamespaces?: string[];
|
@observable private loadedNamespaces?: string[];
|
||||||
|
|
||||||
get contextReady() {
|
namespacesReady = when(() => Boolean(this.loadedNamespaces));
|
||||||
return when(() => Boolean(this.context));
|
|
||||||
}
|
|
||||||
|
|
||||||
get namespacesReady() {
|
constructor(protected cluster: Cluster) {
|
||||||
return when(() => Boolean(this.loadedNamespaces));
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
super();
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
autoBind(this);
|
autoBind(this);
|
||||||
this.bindWatchEventsUpdater();
|
this.bindWatchEventsUpdater();
|
||||||
}
|
}
|
||||||
|
|
||||||
get context(): ClusterContext {
|
|
||||||
return KubeObjectStore.defaultContext.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get contextItems(): T[] {
|
@computed get contextItems(): T[] {
|
||||||
const namespaces = this.context?.contextNamespaces ?? [];
|
const namespaces = contextNamespaces();
|
||||||
|
|
||||||
return this.items.filter(item => {
|
return this.items.filter(item => {
|
||||||
const itemNamespace = item.getNs();
|
const itemNamespace = item.getNs();
|
||||||
@ -95,9 +85,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
|
|
||||||
if (namespaces.length) {
|
if (namespaces.length) {
|
||||||
return this.items.filter(item => namespaces.includes(item.getNs()));
|
return this.items.filter(item => namespaces.includes(item.getNs()));
|
||||||
}
|
} else if (!strict) {
|
||||||
|
|
||||||
if (!strict) {
|
|
||||||
return this.items;
|
return this.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,26 +126,22 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async loadItems({ namespaces, api, reqInit }: KubeObjectStoreLoadingParams<T>): Promise<T[]> {
|
protected async loadItems({ namespaces, api, reqInit }: KubeObjectStoreLoadingParams<T>): Promise<T[]> {
|
||||||
if (this.context?.cluster.isAllowedResource(api.kind)) {
|
if (this.cluster.isAllowedResource(api.kind)) {
|
||||||
if (!api.isNamespaced) {
|
if (!api.isNamespaced) {
|
||||||
return api.list({ reqInit }, this.query);
|
return api.list({ reqInit }, this.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isLoadingAll = this.context.allNamespaces?.length > 1
|
if (isLoadingAll(this.cluster, namespaces)) {
|
||||||
&& this.context.cluster.accessibleNamespaces.length === 0
|
|
||||||
&& this.context.allNamespaces.every(ns => namespaces.includes(ns));
|
|
||||||
|
|
||||||
if (isLoadingAll) {
|
|
||||||
this.loadedNamespaces = [];
|
this.loadedNamespaces = [];
|
||||||
|
|
||||||
return api.list({ reqInit }, this.query);
|
return api.list({ reqInit }, this.query);
|
||||||
} else {
|
|
||||||
this.loadedNamespaces = namespaces;
|
|
||||||
|
|
||||||
return Promise // load resources per namespace
|
|
||||||
.all(namespaces.map(namespace => api.list({ namespace, reqInit })))
|
|
||||||
.then(items => items.flat().filter(Boolean));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.loadedNamespaces = namespaces;
|
||||||
|
|
||||||
|
return Promise // load resources per namespace
|
||||||
|
.all(namespaces.map(namespace => api.list({ namespace, reqInit })))
|
||||||
|
.then(items => items.flat().filter(Boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
@ -169,12 +153,11 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
async loadAll(options: { namespaces?: string[], merge?: boolean, reqInit?: RequestInit } = {}): Promise<void | T[]> {
|
async loadAll(options: { namespaces?: string[], merge?: boolean, reqInit?: RequestInit } = {}): Promise<void | T[]> {
|
||||||
await this.contextReady;
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
namespaces = this.context.allNamespaces, // load all namespaces by default
|
namespaces = allNamespaces(this.cluster), // load all namespaces by default
|
||||||
merge = true, // merge loaded items or return as result
|
merge = true, // merge loaded items or return as result
|
||||||
reqInit,
|
reqInit,
|
||||||
} = options;
|
} = options;
|
||||||
@ -195,7 +178,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
if (error.message) {
|
if (error.message) {
|
||||||
Notifications.error(error.message);
|
Notifications.error(error.message);
|
||||||
}
|
}
|
||||||
console.warn("[KubeObjectStore] loadAll failed", this.api.apiBase, error);
|
console.error("Loading store items failed", { error });
|
||||||
this.resetOnError(error);
|
this.resetOnError(error);
|
||||||
this.failedLoading = true;
|
this.failedLoading = true;
|
||||||
} finally {
|
} finally {
|
||||||
@ -279,10 +262,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(item: T, data: Partial<T>): Promise<T> {
|
async update(item: T, data: Partial<T>): Promise<T> {
|
||||||
const newItem = await item.update(data);
|
const newItem = await item.update<T>(data);
|
||||||
|
|
||||||
ensureObjectSelfLink(this.api, newItem);
|
|
||||||
|
|
||||||
const index = this.items.findIndex(item => item.getId() === newItem.getId());
|
const index = this.items.findIndex(item => item.getId() === newItem.getId());
|
||||||
|
|
||||||
this.items.splice(index, 1, newItem);
|
this.items.splice(index, 1, newItem);
|
||||||
@ -309,35 +289,51 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe() {
|
getSubscribeApis(): KubeApi<T>[] {
|
||||||
const abortController = new AbortController();
|
return [this.api];
|
||||||
|
}
|
||||||
|
|
||||||
if (this.api.isNamespaced) {
|
subscribe(apis = this.getSubscribeApis()) {
|
||||||
Promise.race([rejectPromiseBy(abortController.signal), Promise.all([this.contextReady, this.namespacesReady])])
|
const abortController = new AbortController();
|
||||||
|
const [clusterScopedApis, namespaceScopedApis] = bifurcateArray(apis, api => api.isNamespaced);
|
||||||
|
|
||||||
|
for (const api of namespaceScopedApis) {
|
||||||
|
const store = ApiManager.getInstance().getStore(api);
|
||||||
|
|
||||||
|
// This waits for the context and namespaces to be ready or fails fast if the disposer is called
|
||||||
|
Promise.race([rejectPromiseBy(abortController.signal), Promise.all([store.namespacesReady])])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (this.context.cluster.isGlobalWatchEnabled && this.loadedNamespaces.length === 0) {
|
if (
|
||||||
return this.watchNamespace("", abortController);
|
store.cluster.isGlobalWatchEnabled
|
||||||
|
&& store.loadedNamespaces.length === 0
|
||||||
|
) {
|
||||||
|
return store.watchNamespace(api, "", abortController);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const namespace of this.loadedNamespaces) {
|
for (const namespace of this.loadedNamespaces) {
|
||||||
this.watchNamespace(namespace, abortController);
|
store.watchNamespace(api, namespace, abortController);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(noop); // ignore DOMExceptions
|
.catch(noop); // ignore DOMExceptions
|
||||||
} else {
|
|
||||||
this.watchNamespace("", abortController);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => abortController.abort();
|
for (const api of clusterScopedApis) {
|
||||||
|
/**
|
||||||
|
* if the api is cluster scoped then we will never assign to `loadedNamespaces`
|
||||||
|
* and thus `store.namespacesReady` will never resolve. Futhermore, we don't care
|
||||||
|
* about watching namespaces.
|
||||||
|
*/
|
||||||
|
ApiManager.getInstance().getStore(api).watchNamespace(api, "", abortController);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
abortController.abort();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private watchNamespace(namespace: string, abortController: AbortController) {
|
private watchNamespace(api: KubeApi<T>, namespace: string, abortController: AbortController) {
|
||||||
if (!this.api.getResourceVersion(namespace)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let timedRetry: NodeJS.Timeout;
|
let timedRetry: NodeJS.Timeout;
|
||||||
const watch = () => this.api.watch({
|
const watch = () => api.watch({
|
||||||
namespace,
|
namespace,
|
||||||
abortController,
|
abortController,
|
||||||
callback
|
callback
|
||||||
@ -345,12 +341,12 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
|
|
||||||
const { signal } = abortController;
|
const { signal } = abortController;
|
||||||
|
|
||||||
const callback = (data: IKubeWatchEvent<T>, error: any) => {
|
const callback = (data: IKubeWatchEvent<KubeJsonApiData>, error: any) => {
|
||||||
if (!this.isLoaded || error instanceof DOMException) return;
|
if (!this.isLoaded || error instanceof DOMException) return;
|
||||||
|
|
||||||
if (error instanceof Response) {
|
if (error instanceof Response) {
|
||||||
if (error.status === 404 || error.status === 401) {
|
if (error.status === 404) {
|
||||||
// api has gone, or credentials are not permitted, let's not retry
|
// api has gone, let's not retry
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,12 +379,12 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
protected updateFromEventsBuffer() {
|
protected updateFromEventsBuffer() {
|
||||||
const items = this.getItems();
|
const items = toJS(this.items);
|
||||||
|
|
||||||
for (const { type, object } of this.eventsBuffer.clear()) {
|
for (const { type, object } of this.eventsBuffer.clear()) {
|
||||||
const index = items.findIndex(item => item.getId() === object.metadata?.uid);
|
const index = items.findIndex(item => item.getId() === object.metadata?.uid);
|
||||||
const item = items[index];
|
const item = items[index];
|
||||||
const api = apiManager.getApiByKind(object.kind, object.apiVersion);
|
const api = ApiManager.getInstance().getApiByKind(object.kind, object.apiVersion);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "ADDED":
|
case "ADDED":
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user