mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make sure that stores can still be retrieved
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
886c812679
commit
5856210aa9
@ -24,6 +24,7 @@ import { KubeApi as ExternalKubeApi } from "../../../extensions/common-api/k8s-a
|
|||||||
import { Cluster } from "../../cluster/cluster";
|
import { Cluster } from "../../cluster/cluster";
|
||||||
import { runInAction } from "mobx";
|
import { runInAction } from "mobx";
|
||||||
import { customResourceDefinitionApiInjectionToken } from "../api-manager/crd-api-token";
|
import { customResourceDefinitionApiInjectionToken } from "../api-manager/crd-api-token";
|
||||||
|
import assert from "assert";
|
||||||
|
|
||||||
class TestApi extends KubeApi<KubeObject> {
|
class TestApi extends KubeApi<KubeObject> {
|
||||||
protected async checkPreferredVersion() {
|
protected async checkPreferredVersion() {
|
||||||
@ -156,6 +157,10 @@ describe("ApiManager", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("can have a default KubeObjectStore instance retrieved for it", () => {
|
||||||
|
expect(apiManager.getStore(apiBase)).toBeInstanceOf(KubeObjectStore);
|
||||||
|
});
|
||||||
|
|
||||||
describe("given that an extension registers an api with the same apibase", () => {
|
describe("given that an extension registers an api with the same apibase", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
void Object.assign(new ExternalKubeApi({
|
void Object.assign(new ExternalKubeApi({
|
||||||
@ -172,6 +177,34 @@ describe("ApiManager", () => {
|
|||||||
myField: 2,
|
myField: 2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("can have a default KubeObjectStore instance retrieved for it", () => {
|
||||||
|
expect(apiManager.getStore(apiBase)).toBeInstanceOf(KubeObjectStore);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("given that an extension registers a store for the same apibase", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const api = apiManager.getApi(apiBase);
|
||||||
|
|
||||||
|
assert(api);
|
||||||
|
|
||||||
|
apiManager.registerStore(Object.assign(
|
||||||
|
new KubeObjectStore({
|
||||||
|
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||||
|
logger: di.inject(loggerInjectable),
|
||||||
|
}, api),
|
||||||
|
{
|
||||||
|
someField: 2,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can gets the custom KubeObjectStore instance instead", () => {
|
||||||
|
expect(apiManager.getStore(apiBase)).toMatchObject({
|
||||||
|
someField: 2,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import { autorun, action, observable } from "mobx";
|
|||||||
import type { KubeApi } from "../kube-api";
|
import type { KubeApi } from "../kube-api";
|
||||||
import type { KubeObject, ObjectReference } from "../kube-object";
|
import type { KubeObject, ObjectReference } from "../kube-object";
|
||||||
import { parseKubeApi, createKubeApiURL } from "../kube-api-parse";
|
import { parseKubeApi, createKubeApiURL } from "../kube-api-parse";
|
||||||
import { iter } from "@k8slens/utilities";
|
import { getOrInsertWith, iter } from "@k8slens/utilities";
|
||||||
|
import type { CreateCustomResourceStore } from "./create-custom-resource-store.injectable";
|
||||||
|
|
||||||
export type RegisterableStore<Store> = Store extends KubeObjectStore<any, any, any>
|
export type RegisterableStore<Store> = Store extends KubeObjectStore<any, any, any>
|
||||||
? Store
|
? Store
|
||||||
@ -28,12 +29,13 @@ interface Dependencies {
|
|||||||
readonly apis: IComputedValue<KubeApi[]>;
|
readonly apis: IComputedValue<KubeApi[]>;
|
||||||
readonly crdApis: IComputedValue<KubeApi[]>;
|
readonly crdApis: IComputedValue<KubeApi[]>;
|
||||||
readonly stores: IComputedValue<KubeObjectStore[]>;
|
readonly stores: IComputedValue<KubeObjectStore[]>;
|
||||||
|
createCustomResourceStore: CreateCustomResourceStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ApiManager {
|
export class ApiManager {
|
||||||
private readonly externalApis = observable.array<KubeApi>();
|
private readonly externalApis = observable.array<KubeApi>();
|
||||||
private readonly externalStores = observable.array<KubeObjectStore>();
|
private readonly externalStores = observable.array<KubeObjectStore>();
|
||||||
|
private readonly defaultCrdStores = observable.map<string, KubeObjectStore>();
|
||||||
private readonly apis = observable.map<string, KubeApi>();
|
private readonly apis = observable.map<string, KubeApi>();
|
||||||
|
|
||||||
constructor(private readonly dependencies: Dependencies) {
|
constructor(private readonly dependencies: Dependencies) {
|
||||||
@ -117,6 +119,16 @@ export class ApiManager {
|
|||||||
this.externalStores.push(store);
|
this.externalStores.push(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private apiIsDefaultCrdApi(api: KubeApi): boolean {
|
||||||
|
for (const crdApi of this.dependencies.crdApis.get()) {
|
||||||
|
if (crdApi.apiBase === api.apiBase) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
getStore(api: string | undefined): KubeObjectStore | undefined;
|
getStore(api: string | undefined): KubeObjectStore | undefined;
|
||||||
getStore<Api>(api: RegisterableApi<Api>): KubeObjectStoreFrom<Api> | undefined;
|
getStore<Api>(api: RegisterableApi<Api>): KubeObjectStoreFrom<Api> | undefined;
|
||||||
/**
|
/**
|
||||||
@ -137,9 +149,19 @@ export class ApiManager {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iter.chain(this.dependencies.stores.get().values())
|
const defaultResult = iter.chain(this.dependencies.stores.get().values())
|
||||||
.concat(this.externalStores.values())
|
.concat(this.externalStores.values())
|
||||||
.find(store => store.api.apiBase === api.apiBase);
|
.find(store => store.api.apiBase === api.apiBase);
|
||||||
|
|
||||||
|
if (defaultResult) {
|
||||||
|
return defaultResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.apiIsDefaultCrdApi(api)) {
|
||||||
|
return getOrInsertWith(this.defaultCrdStores, api.apiBase, () => this.dependencies.createCustomResourceStore(api));
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
lookupApiLink(ref: ObjectReference, parentObject?: KubeObject): string {
|
lookupApiLink(ref: ObjectReference, parentObject?: KubeObject): string {
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import clusterFrameContextForNamespacedResourcesInjectable from "../../../renderer/cluster-frame-context/for-namespaced-resources.injectable";
|
||||||
|
import loggerInjectable from "../../logger.injectable";
|
||||||
|
import type { KubeApi } from "../kube-api";
|
||||||
|
import type { KubeObject } from "../kube-object";
|
||||||
|
import type { KubeObjectStoreDependencies } from "../kube-object.store";
|
||||||
|
import { CustomResourceStore } from "./resource.store";
|
||||||
|
|
||||||
|
export type CreateCustomResourceStore = <K extends KubeObject>(api: KubeApi<K>) => CustomResourceStore<K>;
|
||||||
|
|
||||||
|
const createCustomResourceStoreInjectable = getInjectable({
|
||||||
|
id: "create-custom-resource-store",
|
||||||
|
instantiate: (di): CreateCustomResourceStore => {
|
||||||
|
const deps: KubeObjectStoreDependencies = {
|
||||||
|
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||||
|
logger: di.inject(loggerInjectable),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (api) => new CustomResourceStore(deps, api);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default createCustomResourceStoreInjectable;
|
||||||
@ -10,6 +10,7 @@ import { kubeObjectStoreInjectionToken } from "./kube-object-store-token";
|
|||||||
import { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
|
import { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
|
||||||
import { computed } from "mobx";
|
import { computed } from "mobx";
|
||||||
import { customResourceDefinitionApiInjectionToken } from "./crd-api-token";
|
import { customResourceDefinitionApiInjectionToken } from "./crd-api-token";
|
||||||
|
import createCustomResourceStoreInjectable from "./create-custom-resource-store.injectable";
|
||||||
|
|
||||||
const apiManagerInjectable = getInjectable({
|
const apiManagerInjectable = getInjectable({
|
||||||
id: "api-manager",
|
id: "api-manager",
|
||||||
@ -27,6 +28,7 @@ const apiManagerInjectable = getInjectable({
|
|||||||
crdApis: storesAndApisCanBeCreated
|
crdApis: storesAndApisCanBeCreated
|
||||||
? computedInjectMany(customResourceDefinitionApiInjectionToken)
|
? computedInjectMany(customResourceDefinitionApiInjectionToken)
|
||||||
: computed(() => []),
|
: computed(() => []),
|
||||||
|
createCustomResourceStore: di.inject(createCustomResourceStoreInjectable),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -88,7 +88,7 @@ export interface KubeObjectStoreDependencies {
|
|||||||
readonly logger: Logger;
|
readonly logger: Logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class KubeObjectStore<
|
export class KubeObjectStore<
|
||||||
K extends KubeObject = KubeObject,
|
K extends KubeObject = KubeObject,
|
||||||
A extends KubeApi<K, D> = KubeApi<K, KubeJsonApiDataFor<K>>,
|
A extends KubeApi<K, D> = KubeApi<K, KubeJsonApiDataFor<K>>,
|
||||||
D extends KubeJsonApiDataFor<K> = KubeApiDataFrom<K, A>,
|
D extends KubeJsonApiDataFor<K> = KubeApiDataFrom<K, A>,
|
||||||
|
|||||||
@ -5,59 +5,17 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
|
import autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
|
||||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||||
import { CustomResourceStore } from "../../../common/k8s-api/api-manager/resource.store";
|
import type { KubeApi } from "../../../common/k8s-api/kube-api";
|
||||||
import type { CustomResourceDefinition } from "../../../common/k8s-api/endpoints";
|
|
||||||
import type { KubeApiDependencies } from "../../../common/k8s-api/kube-api";
|
|
||||||
import { KubeApi } from "../../../common/k8s-api/kube-api";
|
|
||||||
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
|
||||||
import { beforeClusterFrameStartsSecondInjectionToken } from "../tokens";
|
import { beforeClusterFrameStartsSecondInjectionToken } from "../tokens";
|
||||||
import type { KubeObjectStoreDependencies } from "../../../common/k8s-api/kube-object.store";
|
|
||||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
|
||||||
import loggerInjectable from "../../../common/logger.injectable";
|
|
||||||
import maybeKubeApiInjectable from "../../../common/k8s-api/maybe-kube-api.injectable";
|
|
||||||
|
|
||||||
const setupAutoRegistrationInjectable = getInjectable({
|
const setupAutoRegistrationInjectable = getInjectable({
|
||||||
id: "setup-auto-registration",
|
id: "setup-auto-registration",
|
||||||
instantiate: (di) => ({
|
instantiate: (di) => ({
|
||||||
run: () => {
|
run: () => {
|
||||||
const autoRegistrationEmitter = di.inject(autoRegistrationEmitterInjectable);
|
const autoRegistrationEmitter = di.inject(autoRegistrationEmitterInjectable);
|
||||||
const beforeApiManagerInitializationCrds: CustomResourceDefinition[] = [];
|
|
||||||
const beforeApiManagerInitializationApis: KubeApi[] = [];
|
const beforeApiManagerInitializationApis: KubeApi[] = [];
|
||||||
const kubeApiDependencies: KubeApiDependencies = {
|
|
||||||
logger: di.inject(loggerInjectable),
|
|
||||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
|
||||||
};
|
|
||||||
const kubeObjectStoreDependencies: KubeObjectStoreDependencies = {
|
|
||||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
|
||||||
logger: di.inject(loggerInjectable),
|
|
||||||
};
|
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
|
|
||||||
const autoInitCustomResourceStore = (crd: CustomResourceDefinition) => {
|
|
||||||
const objectConstructor = class extends KubeObject {
|
|
||||||
static readonly kind = crd.getResourceKind();
|
|
||||||
static readonly namespaced = crd.isNamespaced();
|
|
||||||
static readonly apiBase = crd.getResourceApiBase();
|
|
||||||
};
|
|
||||||
|
|
||||||
const api = (() => {
|
|
||||||
const rawApi = apiManager.getApi(objectConstructor.apiBase);
|
|
||||||
|
|
||||||
if (rawApi) {
|
|
||||||
return rawApi;
|
|
||||||
}
|
|
||||||
|
|
||||||
const api = new KubeApi(kubeApiDependencies, { objectConstructor });
|
|
||||||
|
|
||||||
apiManager.registerApi(api);
|
|
||||||
|
|
||||||
return api;
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (!apiManager.getStore(api)) {
|
|
||||||
apiManager.registerStore(new CustomResourceStore(kubeObjectStoreDependencies, api));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const autoInitKubeApi = (api: KubeApi) => {
|
const autoInitKubeApi = (api: KubeApi) => {
|
||||||
apiManager.registerApi(api);
|
apiManager.registerApi(api);
|
||||||
};
|
};
|
||||||
@ -74,7 +32,6 @@ const setupAutoRegistrationInjectable = getInjectable({
|
|||||||
// NOTE: this MUST happen after the event emitter listeners are registered
|
// NOTE: this MUST happen after the event emitter listeners are registered
|
||||||
const apiManager = di.inject(apiManagerInjectable);
|
const apiManager = di.inject(apiManagerInjectable);
|
||||||
|
|
||||||
beforeApiManagerInitializationCrds.forEach(autoInitCustomResourceStore);
|
|
||||||
beforeApiManagerInitializationApis.forEach(autoInitKubeApi);
|
beforeApiManagerInitializationApis.forEach(autoInitKubeApi);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user