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

Fix integration test and kube watches not working at all

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-11-29 14:16:04 -05:00
parent 883bd36028
commit c0ba030785
3 changed files with 28 additions and 28 deletions

View File

@ -403,10 +403,11 @@ export class KubeApi<
/** /**
* This method differs from {@link formatUrlForNotListing} because this treats `""` as "all namespaces" * This method differs from {@link formatUrlForNotListing} because this treats `""` as "all namespaces"
* NOTE: This is also useful for watching
* @param namespace The namespace to list in or `""` for all namespaces * @param namespace The namespace to list in or `""` for all namespaces
*/ */
formatUrlForListing(namespace: string) { formatUrlForListing(namespace: string | undefined, query?: Partial<KubeApiQueryParams>) {
return createKubeApiURL({ const resourcePath = createKubeApiURL({
apiPrefix: this.apiPrefix, apiPrefix: this.apiPrefix,
apiVersion: this.apiVersionWithGroup, apiVersion: this.apiVersionWithGroup,
resource: this.apiResource, resource: this.apiResource,
@ -414,15 +415,15 @@ export class KubeApi<
? namespace ?? "default" ? namespace ?? "default"
: undefined, : undefined,
}); });
return resourcePath + (query ? `?${stringify(this.normalizeQuery(query))}` : "");
} }
/** /**
* Format a URL pathname and query for acting upon a specific resource. * Format a URL pathname and query for acting upon a specific resource.
*/ */
formatUrlForNotListing(resource?: Partial<ResourceDescriptor>, query?: Partial<KubeApiQueryParams>): string; formatUrlForNotListing({ name, namespace }: Partial<ResourceDescriptor> = {}) {
return createKubeApiURL({
formatUrlForNotListing({ name, namespace }: Partial<ResourceDescriptor> = {}, query?: Partial<KubeApiQueryParams>) {
const resourcePath = createKubeApiURL({
apiPrefix: this.apiPrefix, apiPrefix: this.apiPrefix,
apiVersion: this.apiVersionWithGroup, apiVersion: this.apiVersionWithGroup,
resource: this.apiResource, resource: this.apiResource,
@ -431,15 +432,17 @@ export class KubeApi<
: undefined, : undefined,
name, name,
}); });
return resourcePath + (query ? `?${stringify(this.normalizeQuery(query))}` : "");
} }
/** /**
* @deprecated use {@link formatUrlForNotListing} instead * @deprecated use {@link formatUrlForNotListing} or {@link formatUrlForListing} instead
*/ */
getUrl(resource?: Partial<ResourceDescriptor>, query?: Partial<KubeApiQueryParams>) { getUrl(resource?: Partial<ResourceDescriptor>, query?: Partial<KubeApiQueryParams>) {
return this.formatUrlForNotListing(resource, query); if (query) {
return this.formatUrlForListing(resource?.namespace, query);
}
return this.formatUrlForNotListing(resource);
} }
protected normalizeQuery(query: Partial<KubeApiQueryParams> = {}) { protected normalizeQuery(query: Partial<KubeApiQueryParams> = {}) {
@ -625,14 +628,14 @@ export class KubeApi<
} }
getWatchUrl(namespace?: string, query: KubeApiQueryParams = {}) { getWatchUrl(namespace?: string, query: KubeApiQueryParams = {}) {
return this.formatUrlForNotListing({ namespace }, { return this.formatUrlForListing(namespace, {
watch: 1, watch: 1,
resourceVersion: this.getResourceVersion(namespace), resourceVersion: this.getResourceVersion(namespace),
...query, ...query,
}); });
} }
watch(opts?: KubeApiWatchOptions<Object, Data>): () => void { watch(opts?: KubeApiWatchOptions<Object, Data>): Disposer {
let errorReceived = false; let errorReceived = false;
let timedRetry: NodeJS.Timeout; let timedRetry: NodeJS.Timeout;
const { const {

View File

@ -412,7 +412,7 @@ export abstract class KubeObjectStore<
if (this.api.isNamespaced) { if (this.api.isNamespaced) {
void (async () => { void (async () => {
try { try {
const [loadedNamespaces] = await Promise.race([ const loadedNamespaces = await Promise.race([
rejectPromiseBy(abortController.signal), rejectPromiseBy(abortController.signal),
waitUntilDefined(() => this.loadedNamespaces.get()), waitUntilDefined(() => this.loadedNamespaces.get()),
]); ]);
@ -424,8 +424,8 @@ export abstract class KubeObjectStore<
this.watchNamespace(namespace, abortController, { onLoadFailure }); this.watchNamespace(namespace, abortController, { onLoadFailure });
} }
} }
} catch { } catch (error) {
// ignore console.error(`[KUBE-OBJECT-STORE]: failed to subscribe to ${this.api.apiBase}`, error);
} }
})(); })();
} else { } else {
@ -441,7 +441,7 @@ export abstract class KubeObjectStore<
} }
let timedRetry: NodeJS.Timeout; let timedRetry: NodeJS.Timeout;
const watch = () => this.api.watch({ const startNewWatch = () => this.api.watch({
namespace, namespace,
abortController, abortController,
callback, callback,
@ -460,7 +460,7 @@ export abstract class KubeObjectStore<
// not sure what to do, best to retry // not sure what to do, best to retry
clearTimeout(timedRetry); clearTimeout(timedRetry);
timedRetry = setTimeout(watch, 5000); timedRetry = setTimeout(startNewWatch, 5000);
} else if (error instanceof KubeStatus && error.code === 410) { } else if (error instanceof KubeStatus && error.code === 410) {
clearTimeout(timedRetry); clearTimeout(timedRetry);
// resourceVersion has gone, let's try to reload // resourceVersion has gone, let's try to reload
@ -469,11 +469,11 @@ export abstract class KubeObjectStore<
namespace namespace
? this.loadAll({ namespaces: [namespace], reqInit: { signal }, ...opts }) ? this.loadAll({ namespaces: [namespace], reqInit: { signal }, ...opts })
: this.loadAll({ merge: false, reqInit: { signal }, ...opts }) : this.loadAll({ merge: false, reqInit: { signal }, ...opts })
).then(watch); ).then(startNewWatch);
}, 1000); }, 1000);
} else if (error) { // not sure what to do, best to retry } else if (error) { // not sure what to do, best to retry
clearTimeout(timedRetry); clearTimeout(timedRetry);
timedRetry = setTimeout(watch, 5000); timedRetry = setTimeout(startNewWatch, 5000);
} }
if (data) { if (data) {
@ -482,7 +482,7 @@ export abstract class KubeObjectStore<
}; };
signal.addEventListener("abort", () => clearTimeout(timedRetry)); signal.addEventListener("abort", () => clearTimeout(timedRetry));
watch(); startNewWatch();
} }
@action @action

View File

@ -8,26 +8,23 @@ import type { Disposer } from "./disposer";
export async function waitUntilDefined<T>(getter: (() => T | null | undefined) | IComputedValue<T | null | undefined>, opts?: { timeout?: number }): Promise<T> { export async function waitUntilDefined<T>(getter: (() => T | null | undefined) | IComputedValue<T | null | undefined>, opts?: { timeout?: number }): Promise<T> {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
let res: T | null | undefined;
when( when(
() => { () => {
res = typeof getter === "function" const res = typeof getter === "function"
? getter() ? getter()
: getter.get(); : getter.get();
const isDefined = res != null;
if (res != null) { if (isDefined) {
resolve(res); resolve(res);
return true;
} }
return false; return isDefined;
}, },
() => {}, () => {},
{ {
onError: reject, onError: reject,
...opts, ...(opts ?? {}),
}, },
); );
}); });