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

Fix ApiManager not handling duplicate apiBases of KubeApis (#7235)

* Add failing unit test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix failing unit test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

---------

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-02-24 07:44:19 -08:00 committed by GitHub
parent 2550b1efbd
commit f2a229cef6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 7 deletions

View File

@ -19,6 +19,9 @@ import { KubeObject } from "../kube-object";
import { KubeObjectStore } from "../kube-object.store"; import { KubeObjectStore } from "../kube-object.store";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
// eslint-disable-next-line no-restricted-imports
import { KubeApi as ExternalKubeApi } from "../../../extensions/common-api/k8s-api";
class TestApi extends KubeApi<KubeObject> { class TestApi extends KubeApi<KubeObject> {
protected async checkPreferredVersion() { protected async checkPreferredVersion() {
return; return;
@ -54,7 +57,7 @@ describe("ApiManager", () => {
}); });
describe("registerApi", () => { describe("registerApi", () => {
it("re-register store if apiBase changed", async () => { it("re-register store if apiBase changed", () => {
const apiBase = "apis/v1/foo"; const apiBase = "apis/v1/foo";
const fallbackApiBase = "/apis/extensions/v1beta1/foo"; const fallbackApiBase = "/apis/extensions/v1beta1/foo";
const kubeApi = new TestApi({ const kubeApi = new TestApi({
@ -72,21 +75,48 @@ describe("ApiManager", () => {
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
}, kubeApi); }, kubeApi);
apiManager.registerApi(apiBase, kubeApi); apiManager.registerApi(kubeApi);
// Define to use test api for ingress store // Define to use test api for ingress store
Object.defineProperty(kubeStore, "api", { value: kubeApi }); Object.defineProperty(kubeStore, "api", { value: kubeApi });
apiManager.registerStore(kubeStore, [kubeApi]); apiManager.registerStore(kubeStore);
// Test that store is returned with original apiBase // Test that store is returned with original apiBase
expect(apiManager.getStore(kubeApi)).toBe(kubeStore); expect(apiManager.getStore(kubeApi)).toBe(kubeStore);
// Change apiBase similar as checkPreferredVersion does // Change apiBase similar as checkPreferredVersion does
Object.defineProperty(kubeApi, "apiBase", { value: fallbackApiBase }); Object.defineProperty(kubeApi, "apiBase", { value: fallbackApiBase });
apiManager.registerApi(fallbackApiBase, kubeApi); apiManager.registerApi(kubeApi);
// Test that store is returned with new apiBase // Test that store is returned with new apiBase
expect(apiManager.getStore(kubeApi)).toBe(kubeStore); expect(apiManager.getStore(kubeApi)).toBe(kubeStore);
}); });
}); });
describe("technical tests for autorun", () => {
it("given two extensions register apis with the same apibase, settle into using the second", () => {
const apiBase = "/apis/aquasecurity.github.io/v1alpha1/vulnerabilityreports";
const firstApi = Object.assign(new ExternalKubeApi({
objectConstructor: KubeObject,
apiBase,
kind: "VulnerabilityReport",
}), {
myField: 1,
});
const secondApi = Object.assign(new ExternalKubeApi({
objectConstructor: KubeObject,
apiBase,
kind: "VulnerabilityReport",
}), {
myField: 2,
});
void firstApi;
void secondApi;
expect(apiManager.getApi(apiBase)).toMatchObject({
myField: 2,
});
});
});
}); });

View File

@ -41,19 +41,22 @@ export class ApiManager {
const apis = chain(this.dependencies.apis.get().values()) const apis = chain(this.dependencies.apis.get().values())
.concat(this.externalApis.values()); .concat(this.externalApis.values());
const removedApis = new Set(this.apis.values()); const removedApis = new Set(this.apis.values());
const newState = new Map(this.apis);
for (const api of apis) { for (const api of apis) {
removedApis.delete(api); removedApis.delete(api);
this.apis.set(api.apiBase, api); newState.set(api.apiBase, api);
} }
for (const api of removedApis) { for (const api of removedApis) {
for (const [apiBase, storedApi] of this.apis) { for (const [apiBase, storedApi] of newState) {
if (storedApi === api) { if (storedApi === api) {
this.apis.delete(apiBase); newState.delete(apiBase);
} }
} }
} }
this.apis.replace(newState);
}); });
} }