mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fix api-manager.test.ts
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
1c56971e68
commit
d216b8915b
@ -3,7 +3,9 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { apiManager } from "../api-manager";
|
import { getDiForUnitTesting } from "../../../renderer/getDiForUnitTesting";
|
||||||
|
import type { ApiManager } from "../api-manager";
|
||||||
|
import apiManagerInjectable from "../api-manager/manager.injectable";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeObjectStore } from "../kube-object.store";
|
import { KubeObjectStore } from "../kube-object.store";
|
||||||
@ -19,6 +21,14 @@ class TestStore extends KubeObjectStore<KubeObject, TestApi> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("ApiManager", () => {
|
describe("ApiManager", () => {
|
||||||
|
let apiManager: ApiManager;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
|
||||||
|
apiManager = di.inject(apiManagerInjectable);
|
||||||
|
});
|
||||||
|
|
||||||
describe("registerApi", () => {
|
describe("registerApi", () => {
|
||||||
it("re-register store if apiBase changed", async () => {
|
it("re-register store if apiBase changed", async () => {
|
||||||
const apiBase = "apis/v1/foo";
|
const apiBase = "apis/v1/foo";
|
||||||
@ -26,6 +36,7 @@ describe("ApiManager", () => {
|
|||||||
const kubeApi = new TestApi({
|
const kubeApi = new TestApi({
|
||||||
objectConstructor: KubeObject,
|
objectConstructor: KubeObject,
|
||||||
apiBase,
|
apiBase,
|
||||||
|
kind: "foo",
|
||||||
fallbackApiBases: [fallbackApiBase],
|
fallbackApiBases: [fallbackApiBase],
|
||||||
checkPreferredVersion: true,
|
checkPreferredVersion: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import type { Logger } from "../logger";
|
|||||||
/**
|
/**
|
||||||
* The options used for creating a `KubeApi`
|
* The options used for creating a `KubeApi`
|
||||||
*/
|
*/
|
||||||
export interface IKubeApiOptions<T extends KubeObject<any, any, KubeObjectScope>, Data extends KubeJsonApiDataFor<T> = KubeJsonApiDataFor<T>> extends DerivedKubeApiOptions {
|
export interface KubeApiOptions<T extends KubeObject<any, any, KubeObjectScope>, Data extends KubeJsonApiDataFor<T> = KubeJsonApiDataFor<T>> extends DerivedKubeApiOptions {
|
||||||
/**
|
/**
|
||||||
* base api-path for listing all resources, e.g. "/api/v1/pods"
|
* base api-path for listing all resources, e.g. "/api/v1/pods"
|
||||||
*
|
*
|
||||||
@ -173,19 +173,19 @@ export interface IRemoteKubeApiConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function forCluster<
|
export function forCluster<
|
||||||
T extends KubeObject<any, any, KubeObjectScope>,
|
Object extends KubeObject<any, any, KubeObjectScope>,
|
||||||
Y extends KubeApi<T>,
|
Api extends KubeApi<Object>,
|
||||||
Data extends KubeJsonApiDataFor<T>,
|
Data extends KubeJsonApiDataFor<Object>,
|
||||||
>(cluster: ILocalKubeApiConfig, kubeClass: KubeObjectConstructor<T, Data>, apiClass: new (apiOpts: IKubeApiOptions<T>) => Y): Y;
|
>(cluster: ILocalKubeApiConfig, kubeClass: KubeObjectConstructor<Object, Data>, apiClass: new (apiOpts: KubeApiOptions<Object>) => Api): Api;
|
||||||
export function forCluster<
|
export function forCluster<
|
||||||
T extends KubeObject<any, any, KubeObjectScope>,
|
Object extends KubeObject<any, any, KubeObjectScope>,
|
||||||
Data extends KubeJsonApiDataFor<T>,
|
Data extends KubeJsonApiDataFor<Object>,
|
||||||
>(cluster: ILocalKubeApiConfig, kubeClass: KubeObjectConstructor<T, Data>, apiClass?: new (apiOpts: IKubeApiOptions<T>) => KubeApi<T>): KubeApi<T>;
|
>(cluster: ILocalKubeApiConfig, kubeClass: KubeObjectConstructor<Object, Data>, apiClass?: new (apiOpts: KubeApiOptions<Object>) => KubeApi<Object>): KubeApi<Object>;
|
||||||
|
|
||||||
export function forCluster<
|
export function forCluster<
|
||||||
T extends KubeObject<any, any, KubeObjectScope>,
|
Object extends KubeObject<any, any, KubeObjectScope>,
|
||||||
Data extends KubeJsonApiDataFor<T>,
|
Data extends KubeJsonApiDataFor<Object>,
|
||||||
>(cluster: ILocalKubeApiConfig, kubeClass: KubeObjectConstructor<T, Data>, apiClass: (new (apiOpts: IKubeApiOptions<T>) => KubeApi<T>) = KubeApi): KubeApi<T> {
|
>(cluster: ILocalKubeApiConfig, kubeClass: KubeObjectConstructor<Object, Data>, apiClass: (new (apiOpts: KubeApiOptions<Object>) => KubeApi<Object>) = KubeApi): KubeApi<Object> {
|
||||||
const url = new URL(apiBase.config.serverAddress);
|
const url = new URL(apiBase.config.serverAddress);
|
||||||
const request = new KubeJsonApi({
|
const request = new KubeJsonApi({
|
||||||
serverAddress: apiBase.config.serverAddress,
|
serverAddress: apiBase.config.serverAddress,
|
||||||
@ -198,26 +198,26 @@ export function forCluster<
|
|||||||
});
|
});
|
||||||
|
|
||||||
return new apiClass({
|
return new apiClass({
|
||||||
objectConstructor: kubeClass as KubeObjectConstructor<T, KubeJsonApiDataFor<T>>,
|
objectConstructor: kubeClass as KubeObjectConstructor<Object, KubeJsonApiDataFor<Object>>,
|
||||||
request,
|
request,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function forRemoteCluster<
|
export function forRemoteCluster<
|
||||||
T extends KubeObject<any, any, KubeObjectScope>,
|
Object extends KubeObject<any, any, KubeObjectScope>,
|
||||||
Y extends KubeApi<T>,
|
Api extends KubeApi<Object>,
|
||||||
Data extends KubeJsonApiDataFor<T>,
|
Data extends KubeJsonApiDataFor<Object>,
|
||||||
>(config: IRemoteKubeApiConfig, kubeClass: KubeObjectConstructor<T, Data>, apiClass: new (apiOpts: IKubeApiOptions<T>) => Y): Y;
|
>(config: IRemoteKubeApiConfig, kubeClass: KubeObjectConstructor<Object, Data>, apiClass: new (apiOpts: KubeApiOptions<Object>) => Api): Api;
|
||||||
export function forRemoteCluster<
|
export function forRemoteCluster<
|
||||||
T extends KubeObject<any, any, KubeObjectScope>,
|
Object extends KubeObject<any, any, KubeObjectScope>,
|
||||||
Data extends KubeJsonApiDataFor<T>,
|
Data extends KubeJsonApiDataFor<Object>,
|
||||||
>(config: IRemoteKubeApiConfig, kubeClass: KubeObjectConstructor<T, Data>, apiClass?: new (apiOpts: IKubeApiOptions<T>) => KubeApi<T>): KubeApi<T>;
|
>(config: IRemoteKubeApiConfig, kubeClass: KubeObjectConstructor<Object, Data>, apiClass?: new (apiOpts: KubeApiOptions<Object>) => KubeApi<Object>): KubeApi<Object>;
|
||||||
|
|
||||||
export function forRemoteCluster<
|
export function forRemoteCluster<
|
||||||
K extends KubeObject<any, any, KubeObjectScope>,
|
Object extends KubeObject<any, any, KubeObjectScope>,
|
||||||
Y extends KubeApi<K>,
|
Api extends KubeApi<Object>,
|
||||||
Data extends KubeJsonApiDataFor<K>,
|
Data extends KubeJsonApiDataFor<Object>,
|
||||||
>(config: IRemoteKubeApiConfig, kubeClass: KubeObjectConstructor<K, Data>, apiClass: new (apiOpts: IKubeApiOptions<K>) => KubeApi<K> = KubeApi): KubeApi<K> {
|
>(config: IRemoteKubeApiConfig, kubeClass: KubeObjectConstructor<Object, Data>, apiClass: new (apiOpts: KubeApiOptions<Object>) => KubeApi<Object> = KubeApi): KubeApi<Object> {
|
||||||
const reqInit: RequestInit = {};
|
const reqInit: RequestInit = {};
|
||||||
const agentOptions: AgentOptions = {};
|
const agentOptions: AgentOptions = {};
|
||||||
|
|
||||||
@ -256,18 +256,18 @@ export function forRemoteCluster<
|
|||||||
}, reqInit);
|
}, reqInit);
|
||||||
|
|
||||||
if (!apiClass) {
|
if (!apiClass) {
|
||||||
apiClass = KubeApi as new (apiOpts: IKubeApiOptions<K>) => Y;
|
apiClass = KubeApi as new (apiOpts: KubeApiOptions<Object>) => Api;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new apiClass({
|
return new apiClass({
|
||||||
objectConstructor: kubeClass as KubeObjectConstructor<K, KubeJsonApiDataFor<K>>,
|
objectConstructor: kubeClass as KubeObjectConstructor<Object, KubeJsonApiDataFor<Object>>,
|
||||||
request,
|
request,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export type KubeApiWatchCallback<T extends KubeJsonApiData = KubeJsonApiData> = (data: IKubeWatchEvent<T>, error: any) => void;
|
export type KubeApiWatchCallback<T extends KubeJsonApiData = KubeJsonApiData> = (data: IKubeWatchEvent<T>, error: any) => void;
|
||||||
|
|
||||||
export interface KubeApiWatchOptions<T extends KubeObject<any, any, KubeObjectScope>, Data extends KubeJsonApiDataFor<T>> {
|
export interface KubeApiWatchOptions<Object extends KubeObject<any, any, KubeObjectScope>, Data extends KubeJsonApiDataFor<Object>> {
|
||||||
namespace: string;
|
namespace: string;
|
||||||
callback?: KubeApiWatchCallback<Data> | undefined;
|
callback?: KubeApiWatchCallback<Data> | undefined;
|
||||||
abortController?: AbortController | undefined;
|
abortController?: AbortController | undefined;
|
||||||
@ -310,8 +310,8 @@ export interface DeleteResourceDescriptor extends ResourceDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class KubeApi<
|
export class KubeApi<
|
||||||
K extends KubeObject = KubeObject,
|
Object extends KubeObject = KubeObject,
|
||||||
D extends KubeJsonApiDataFor<K> = KubeJsonApiDataFor<K>,
|
Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>,
|
||||||
> {
|
> {
|
||||||
readonly kind: string;
|
readonly kind: string;
|
||||||
readonly apiVersion: string;
|
readonly apiVersion: string;
|
||||||
@ -322,7 +322,7 @@ export class KubeApi<
|
|||||||
readonly apiResource: string;
|
readonly apiResource: string;
|
||||||
readonly isNamespaced: boolean;
|
readonly isNamespaced: boolean;
|
||||||
|
|
||||||
public readonly objectConstructor: KubeObjectConstructor<K, D>;
|
public readonly objectConstructor: KubeObjectConstructor<Object, Data>;
|
||||||
protected readonly request: KubeJsonApi;
|
protected readonly request: KubeJsonApi;
|
||||||
protected readonly resourceVersions = new Map<string, string>();
|
protected readonly resourceVersions = new Map<string, string>();
|
||||||
protected readonly watchDisposer: Disposer | undefined;
|
protected readonly watchDisposer: Disposer | undefined;
|
||||||
@ -340,15 +340,15 @@ export class KubeApi<
|
|||||||
apiBase: fullApiPathname = objectConstructor.apiBase,
|
apiBase: fullApiPathname = objectConstructor.apiBase,
|
||||||
checkPreferredVersion: doCheckPreferredVersion = false,
|
checkPreferredVersion: doCheckPreferredVersion = false,
|
||||||
fallbackApiBases,
|
fallbackApiBases,
|
||||||
}: IKubeApiOptions<K, D>) {
|
}: KubeApiOptions<Object, Data>) {
|
||||||
assert(fullApiPathname);
|
assert(fullApiPathname, "apiBase MUST be provied either via KubeApiOptions.apiBase or KubeApiOptions.objectConstructor.apiBase");
|
||||||
assert(request, "request MUST be provided if not in a cluster page frame context");
|
assert(request, "request MUST be provided if not in a cluster page frame context");
|
||||||
|
|
||||||
const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parseKubeApi(fullApiPathname);
|
const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parseKubeApi(fullApiPathname);
|
||||||
const di = getLegacyGlobalDiForExtensionApi();
|
const di = getLegacyGlobalDiForExtensionApi();
|
||||||
|
|
||||||
assert(kind);
|
assert(kind, "kind MUST be provied either via KubeApiOptions.kind or KubeApiOptions.objectConstructor.kind");
|
||||||
assert(apiPrefix);
|
assert(apiPrefix, "apiBase MUST be parsable as a kubeApi selfLink style string");
|
||||||
|
|
||||||
this.logger = di.inject(loggerInjectable);
|
this.logger = di.inject(loggerInjectable);
|
||||||
this.doCheckPreferredVersion = doCheckPreferredVersion;
|
this.doCheckPreferredVersion = doCheckPreferredVersion;
|
||||||
@ -364,7 +364,7 @@ export class KubeApi<
|
|||||||
this.request = request;
|
this.request = request;
|
||||||
this.objectConstructor = objectConstructor;
|
this.objectConstructor = objectConstructor;
|
||||||
this.parseResponse = this.parseResponse.bind(this);
|
this.parseResponse = this.parseResponse.bind(this);
|
||||||
apiManager.registerApi<KubeApi<K, D>>(apiBase, this);
|
apiManager.registerApi<KubeApi<Object, Data>>(apiBase, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get apiVersionWithGroup() {
|
get apiVersionWithGroup() {
|
||||||
@ -445,7 +445,7 @@ export class KubeApi<
|
|||||||
|
|
||||||
if (this.apiVersionPreferred) {
|
if (this.apiVersionPreferred) {
|
||||||
this.apiBase = this.computeApiBase();
|
this.apiBase = this.computeApiBase();
|
||||||
apiManager.registerApi<KubeApi<K, D>>(this.apiBase, this);
|
apiManager.registerApi<KubeApi<Object, Data>>(this.apiBase, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,7 +494,7 @@ export class KubeApi<
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected parseResponse(data: unknown, namespace?: string): K | K[] | null {
|
protected parseResponse(data: unknown, namespace?: string): Object | Object[] | null {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -517,7 +517,7 @@ export class KubeApi<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const object = new KubeObjectConstructor({
|
const object = new KubeObjectConstructor({
|
||||||
...(item as D),
|
...(item as Data),
|
||||||
kind: this.kind,
|
kind: this.kind,
|
||||||
apiVersion,
|
apiVersion,
|
||||||
});
|
});
|
||||||
@ -556,7 +556,7 @@ export class KubeApi<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async list({ namespace = "", reqInit }: KubeApiListOptions = {}, query?: KubeApiQueryParams): Promise<K[] | null> {
|
async list({ namespace = "", reqInit }: KubeApiListOptions = {}, query?: KubeApiQueryParams): Promise<Object[] | null> {
|
||||||
await this.checkPreferredVersion();
|
await this.checkPreferredVersion();
|
||||||
|
|
||||||
const url = this.getUrl({ namespace });
|
const url = this.getUrl({ namespace });
|
||||||
@ -574,7 +574,7 @@ export class KubeApi<
|
|||||||
throw new Error(`GET multiple request to ${url} returned not an array: ${JSON.stringify(parsed)}`);
|
throw new Error(`GET multiple request to ${url} returned not an array: ${JSON.stringify(parsed)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(desc: ResourceDescriptor, query?: KubeApiQueryParams): Promise<K | null> {
|
async get(desc: ResourceDescriptor, query?: KubeApiQueryParams): Promise<Object | null> {
|
||||||
await this.checkPreferredVersion();
|
await this.checkPreferredVersion();
|
||||||
|
|
||||||
const url = this.getUrl(desc);
|
const url = this.getUrl(desc);
|
||||||
@ -588,7 +588,7 @@ export class KubeApi<
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async create({ name, namespace }: Partial<ResourceDescriptor>, data?: PartialDeep<K>): Promise<K | null> {
|
async create({ name, namespace }: Partial<ResourceDescriptor>, data?: PartialDeep<Object>): Promise<Object | null> {
|
||||||
await this.checkPreferredVersion();
|
await this.checkPreferredVersion();
|
||||||
|
|
||||||
const apiUrl = this.getUrl({ namespace });
|
const apiUrl = this.getUrl({ namespace });
|
||||||
@ -611,7 +611,7 @@ export class KubeApi<
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async update({ name, namespace }: ResourceDescriptor, data: PartialDeep<K>): Promise<K | null> {
|
async update({ name, namespace }: ResourceDescriptor, data: PartialDeep<Object>): Promise<Object | null> {
|
||||||
await this.checkPreferredVersion();
|
await this.checkPreferredVersion();
|
||||||
const apiUrl = this.getUrl({ namespace, name });
|
const apiUrl = this.getUrl({ namespace, name });
|
||||||
|
|
||||||
@ -632,7 +632,7 @@ export class KubeApi<
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async patch(desc: ResourceDescriptor, data: PartialDeep<K> | Patch, strategy: KubeApiPatchType = "strategic"): Promise<K | null> {
|
async patch(desc: ResourceDescriptor, data: PartialDeep<Object> | Patch, strategy: KubeApiPatchType = "strategic"): Promise<Object | null> {
|
||||||
await this.checkPreferredVersion();
|
await this.checkPreferredVersion();
|
||||||
const apiUrl = this.getUrl(desc);
|
const apiUrl = this.getUrl(desc);
|
||||||
|
|
||||||
@ -669,7 +669,7 @@ export class KubeApi<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(opts: KubeApiWatchOptions<K, D> = { namespace: "", retry: false }): () => void {
|
watch(opts: KubeApiWatchOptions<Object, Data> = { namespace: "", retry: false }): () => void {
|
||||||
let errorReceived = false;
|
let errorReceived = false;
|
||||||
let timedRetry: NodeJS.Timeout;
|
let timedRetry: NodeJS.Timeout;
|
||||||
const { namespace, callback = noop, retry, timeout } = opts;
|
const { namespace, callback = noop, retry, timeout } = opts;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user