diff --git a/src/main/lens-proxy.ts b/src/main/lens-proxy.ts index c58f3eb2e4..177e4d11d2 100644 --- a/src/main/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -194,7 +194,8 @@ export class LensProxy { if (proxyTarget) { // allow to fetch apis in "clusterId.localhost:port" from "localhost:port" - res.setHeader("Access-Control-Allow-Origin", this.origin); + // this should be safe because we have already validated cluster uuid + res.setHeader("Access-Control-Allow-Origin", "*"); return proxy.web(req, res, proxyTarget); } diff --git a/src/renderer/api/json-api.ts b/src/renderer/api/json-api.ts index cfd00e9646..ed9d2b221d 100644 --- a/src/renderer/api/json-api.ts +++ b/src/renderer/api/json-api.ts @@ -55,17 +55,28 @@ export class JsonApi { return this.request(path, params, { ...reqInit, method: "get" }); } - getReadableStream(path: string, params?: P, init: RequestInit = {}): Promise { - let reqUrl = this.config.apiBase + path; + getResponse(reqUrl: string, params?: P, init: RequestInit = { }): Promise { const reqInit: RequestInit = { ...init }; const { query } = params || {} as P; + if (!reqInit.method) { + reqInit.method = "get"; + } + if (query) { const queryString = stringify(query); reqUrl += (reqUrl.includes("?") ? "&" : "?") + queryString; } + const infoLog: JsonApiLog = { + method: `${reqInit.method.toUpperCase()} (stream)`, + reqUrl, + reqInit, + }; + + this.writeLog({ ...infoLog }); + return fetch(reqUrl, reqInit); } diff --git a/src/renderer/api/kube-api.ts b/src/renderer/api/kube-api.ts index 56a0e18825..a193074199 100644 --- a/src/renderer/api/kube-api.ts +++ b/src/renderer/api/kube-api.ts @@ -371,12 +371,15 @@ export class KubeApi { opts.abortController = new AbortController(); } const { abortController, namespace, callback } = opts; - const watchUrl = this.getWatchUrl(namespace); - const responsePromise = this.request.getReadableStream(watchUrl, null, { signal: abortController.signal }); - let disposed = false; + + // FIXME + const watchUrl = `http://${this.kind}-watch.${window.location.host}${apiKubePrefix}${this.getWatchUrl(namespace)}`; + const responsePromise = this.request.getResponse(watchUrl, null, { + signal: abortController.signal + }); responsePromise.then((response) => { - if (!response.ok && !disposed) { + if (!response.ok && !abortController.signal.aborted) { if (response.status === 410) { // resourceVersion has gone setTimeout(() => { this.refreshResourceVersion().then(() => { @@ -399,8 +402,6 @@ export class KubeApi { try { const data: IKubeWatchEvent = JSON.parse(line); - console.log("data", data); - if (callback) { callback(data); } @@ -411,7 +412,7 @@ export class KubeApi { stream.on("close", () => { setTimeout(() => { - if (!disposed) this.watch({...opts, namespace, callback}); + if (!abortController.signal.aborted) this.watch({...opts, namespace, callback}); }, 1000); }); }, (error) => { @@ -423,7 +424,6 @@ export class KubeApi { }); const disposer = () => { - disposed = true; abortController.abort(); }; diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index 5eeb7b2f11..8652f0642c 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -22,6 +22,7 @@ import { MenuItem } from "../menu"; import { Checkbox } from "../checkbox"; import { userStore } from "../../../common/user-store"; import { namespaceStore } from "../+namespaces/namespace.store"; +import { Icon } from "../icon"; // todo: refactor, split to small re-usable components @@ -341,16 +342,17 @@ export class ItemListLayout extends React.Component { const allItemsCount = this.props.store.getTotalCount(); const itemsCount = items.length; const isFiltered = isReady && filters.length > 0; + const RefreshIcon = this.loadStores()} />; if (isFiltered) { const toggleFilters = () => userSettings.showAppliedFilters = !userSettings.showAppliedFilters; return ( - <>Filtered: {itemsCount} / {allItemsCount} + <>Filtered: {itemsCount} / {allItemsCount} {RefreshIcon} ); } - return allItemsCount <= 1 ? `${allItemsCount} item` : `${allItemsCount} items`; + return allItemsCount <= 1 ? <>{allItemsCount} item {RefreshIcon} : <>{allItemsCount} items {RefreshIcon}; } renderHeader() { diff --git a/src/renderer/kube-object.store.ts b/src/renderer/kube-object.store.ts index 830cd7918f..c84608f3ce 100644 --- a/src/renderer/kube-object.store.ts +++ b/src/renderer/kube-object.store.ts @@ -267,16 +267,16 @@ export abstract class KubeObjectStore extends ItemSt } subscribe(apis = this.getSubscribeApis()) { - const abortController = new AbortController(); let disposers: {(): void}[] = []; const callback = (data: IKubeWatchEvent) => { + if (!this.isLoaded) return; + this.eventsBuffer.push(data); }; if (this.context.cluster.isGlobalWatchEnabled) { disposers = apis.map(api => api.watch({ - abortController, namespace: "", callback: (data) => callback(data), })); @@ -284,7 +284,6 @@ export abstract class KubeObjectStore extends ItemSt apis.map(api => { this.loadedNamespaces.forEach((namespace) => { disposers.push(api.watch({ - abortController, namespace, callback: (data) => callback(data) }));