From 7dbece60e9ead93d2155c8ec34ad1e51b88ecd6d Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 3 Jan 2023 14:54:52 -0500 Subject: [PATCH] Add failing test to maintain behaviour Signed-off-by: Sebastian Malton --- .../kube-api-version-detection.test.ts | 4 ++ src/common/k8s-api/api-manager/api-manager.ts | 45 +++++++++++++------ src/common/k8s-api/kube-api.ts | 3 +- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts b/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts index ca6462f9e6..8ba66c476b 100644 --- a/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts +++ b/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts @@ -341,6 +341,10 @@ describe("KubeApi", () => { expect(apiManager.getApi("/apis/networking.k8s.io/v1beta1/ingresses")).toBeDefined(); }); + it("api is retrievable with the old apiBase", () => { + expect(apiManager.getApi("/apis/networking.k8s.io/v1/ingresses")).toBeDefined(); + }); + describe("when the request resolves with no data", () => { let result: Ingress | null; diff --git a/src/common/k8s-api/api-manager/api-manager.ts b/src/common/k8s-api/api-manager/api-manager.ts index c2d52d8a75..48c470da68 100644 --- a/src/common/k8s-api/api-manager/api-manager.ts +++ b/src/common/k8s-api/api-manager/api-manager.ts @@ -6,11 +6,11 @@ import type { KubeObjectStore } from "../kube-object.store"; import type { IComputedValue } from "mobx"; -import { action, observable } from "mobx"; +import { autorun, action, observable } from "mobx"; import type { KubeApi } from "../kube-api"; import type { KubeObject, ObjectReference } from "../kube-object"; import { parseKubeApi, createKubeApiURL } from "../kube-api-parse"; -import { chain } from "../../utils/iter"; +import { chain, find } from "../../utils/iter"; export type RegisterableStore = Store extends KubeObjectStore ? Store @@ -33,20 +33,38 @@ export class ApiManager { private readonly externalApis = observable.array(); private readonly externalStores = observable.array(); - constructor(private readonly dependencies: Dependencies) {} + private readonly apis = observable.map(); + + constructor(private readonly dependencies: Dependencies) { + // NOTE: this is done to preserve the old behaviour of an API being discoverable using all previous apiBases + autorun(() => { + const apis = chain(this.dependencies.apis.get().values()) + .concat(this.externalApis.values()); + const removedApis = new Set(this.apis.values()); + + for (const api of apis) { + removedApis.delete(api); + this.apis.set(api.apiBase, api); + } + + for (const api of removedApis) { + for (const [apiBase, storedApi] of this.apis) { + if (storedApi === api) { + this.apis.delete(apiBase); + } + } + } + }); + } getApi(pathOrCallback: string | FindApiCallback) { - const callback: FindApiCallback = typeof pathOrCallback === "function" - ? pathOrCallback - : (() => { - const { apiBase } = parseKubeApi(pathOrCallback); + if (typeof pathOrCallback === "function") { + return find(this.apis.values(), pathOrCallback); + } - return api => api.apiBase === apiBase; - })(); + const { apiBase } = parseKubeApi(pathOrCallback); - return chain(this.dependencies.apis.get().values()) - .concat(this.externalApis.values()) - .find(callback); + return this.apis.get(apiBase); } getApiByKind(kind: string, apiVersion: string) { @@ -103,10 +121,11 @@ export class ApiManager { const { apiBase } = typeof apiOrBase === "string" ? parseKubeApi(apiOrBase) : apiOrBase; + const api = this.getApi(apiBase); return chain(this.dependencies.stores.get().values()) .concat(this.externalStores.values()) - .find(store => store.api.apiBase === apiBase); + .find(store => store.api === api); } lookupApiLink(ref: ObjectReference, parentObject?: KubeObject): string { diff --git a/src/common/k8s-api/kube-api.ts b/src/common/k8s-api/kube-api.ts index a67111422f..7b9c3f44fb 100644 --- a/src/common/k8s-api/kube-api.ts +++ b/src/common/k8s-api/kube-api.ts @@ -22,7 +22,7 @@ import type { PartialDeep } from "type-fest"; import type { Logger } from "../logger"; import type AbortController from "abort-controller"; import { matches } from "lodash/fp"; -import { action, makeObservable, observable } from "mobx"; +import { makeObservable, observable } from "mobx"; /** * The options used for creating a `KubeApi` @@ -312,7 +312,6 @@ export class KubeApi< throw new Error(`Can't find working API for the Kubernetes resource ${this.apiResource}`); } - @action protected async checkPreferredVersion() { if (this.fallbackApiBases && !this.doCheckPreferredVersion) { throw new Error("checkPreferredVersion must be enabled if fallbackApiBases is set in KubeApi");