From 24db61fbef728a5418040d7cf9154a3c15fd703c Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 12 Apr 2022 10:08:59 -0400 Subject: [PATCH] fix deployments.store.test.ts Signed-off-by: Sebastian Malton --- .../k8s-api/{ => api-manager}/api-manager.ts | 12 ++- src/common/k8s-api/api-manager/index.ts | 7 ++ .../k8s-api/api-manager/legacy-global.ts | 11 +++ .../api-manager/manager.injectable.ts} | 9 +- .../endpoints/deployment.api.injectable.ts | 19 ++++ .../k8s-api/endpoints/deployment.api.ts | 5 -- .../k8s-api/endpoints/legacy-globals.ts | 6 ++ src/common/k8s-api/json-api.ts | 88 +++++++++++++------ src/common/k8s-api/kube-api-parse.ts | 6 +- src/common/k8s-api/kube-api.ts | 67 ++++++++------ src/common/k8s-api/kube-json-api.ts | 6 +- src/common/k8s-api/kube-object.store.ts | 21 +++-- src/common/k8s-api/kube-object.ts | 3 +- src/common/utils/objects.ts | 2 +- src/common/utils/types.ts | 6 +- src/extensions/renderer-api/k8s-api.ts | 2 +- .../cluster-overview-store.injectable.ts | 2 +- .../components/+custom-resources/crd.store.ts | 10 ++- .../namespace-store.injectable.ts | 2 +- .../+network-endpoints/endpoints.store.ts | 10 ++- src/renderer/components/+nodes/nodes.store.ts | 11 ++- .../store.injectable.ts | 2 +- .../+cluster-roles/store.injectable.ts | 2 +- .../+roles/store.injectable.ts | 2 +- .../+service-accounts/store.injectable.ts | 2 +- .../+workloads-daemonsets/store.injectable.ts | 2 +- .../deployment-details.tsx | 7 +- .../deployments-store.injectable.ts | 14 --- .../deployments.store.ts | 53 ----------- .../+workloads-deployments/deployments.tsx | 2 +- .../+workloads-deployments/legacy-store.ts | 12 +++ .../store.injectable.ts | 30 +++++++ .../+workloads-deployments/store.ts | 63 +++++++++++++ .../+workloads-overview/overview.tsx | 2 +- .../deployments-workload.injectable.ts | 2 +- .../workloads/workload-injection-token.ts | 2 +- .../details/volumes/variant-helpers.tsx | 4 +- .../+workloads-pods/store.injectable.ts | 2 +- .../store.injectable.ts | 2 +- .../__tests__/deployments.store.test.ts | 18 +++- .../kube-object-menu.test.tsx | 2 +- .../kube-object-menu/kube-object-menu.tsx | 2 +- 42 files changed, 349 insertions(+), 183 deletions(-) rename src/common/k8s-api/{ => api-manager}/api-manager.ts (94%) create mode 100644 src/common/k8s-api/api-manager/index.ts create mode 100644 src/common/k8s-api/api-manager/legacy-global.ts rename src/{renderer/components/kube-object-menu/dependencies/api-manager.injectable.ts => common/k8s-api/api-manager/manager.injectable.ts} (64%) create mode 100644 src/common/k8s-api/endpoints/deployment.api.injectable.ts delete mode 100644 src/renderer/components/+workloads-deployments/deployments-store.injectable.ts delete mode 100644 src/renderer/components/+workloads-deployments/deployments.store.ts create mode 100644 src/renderer/components/+workloads-deployments/legacy-store.ts create mode 100644 src/renderer/components/+workloads-deployments/store.injectable.ts create mode 100644 src/renderer/components/+workloads-deployments/store.ts diff --git a/src/common/k8s-api/api-manager.ts b/src/common/k8s-api/api-manager/api-manager.ts similarity index 94% rename from src/common/k8s-api/api-manager.ts rename to src/common/k8s-api/api-manager/api-manager.ts index 007483777f..f42ce1d2f4 100644 --- a/src/common/k8s-api/api-manager.ts +++ b/src/common/k8s-api/api-manager/api-manager.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { KubeObjectStore } from "./kube-object.store"; +import type { KubeObjectStore } from "../kube-object.store"; import { action, observable, makeObservable } from "mobx"; -import { autoBind, isDefined, iter } from "../utils"; -import type { KubeApi } from "./kube-api"; -import type { KubeJsonApiDataFor, KubeObject, ObjectReference } from "./kube-object"; -import { parseKubeApi, createKubeApiURL } from "./kube-api-parse"; +import { autoBind, isDefined, iter } from "../../utils"; +import type { KubeApi } from "../kube-api"; +import type { KubeJsonApiDataFor, KubeObject, ObjectReference } from "../kube-object"; +import { parseKubeApi, createKubeApiURL } from "../kube-api-parse"; export type RegisterableStore = Store extends KubeObjectStore ? Store @@ -148,5 +148,3 @@ export class ApiManager { return createKubeApiURL({ apiVersion, name, namespace, resource }); } } - -export const apiManager = new ApiManager(); diff --git a/src/common/k8s-api/api-manager/index.ts b/src/common/k8s-api/api-manager/index.ts new file mode 100644 index 0000000000..105a0f0c9f --- /dev/null +++ b/src/common/k8s-api/api-manager/index.ts @@ -0,0 +1,7 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +export * from "./api-manager"; +export * from "./legacy-global"; diff --git a/src/common/k8s-api/api-manager/legacy-global.ts b/src/common/k8s-api/api-manager/legacy-global.ts new file mode 100644 index 0000000000..846df012fa --- /dev/null +++ b/src/common/k8s-api/api-manager/legacy-global.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { ApiManager } from "./api-manager"; + +/** + * @deprecated use `di.inject(apiManagerInjectable)` instead + */ +export const apiManager = new ApiManager(); diff --git a/src/renderer/components/kube-object-menu/dependencies/api-manager.injectable.ts b/src/common/k8s-api/api-manager/manager.injectable.ts similarity index 64% rename from src/renderer/components/kube-object-menu/dependencies/api-manager.injectable.ts rename to src/common/k8s-api/api-manager/manager.injectable.ts index 0fc1dd740b..970ea02fe4 100644 --- a/src/renderer/components/kube-object-menu/dependencies/api-manager.injectable.ts +++ b/src/common/k8s-api/api-manager/manager.injectable.ts @@ -2,12 +2,17 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { apiManager } from "../../../../common/k8s-api/api-manager"; import { getInjectable } from "@ogre-tools/injectable"; +import { apiManager } from "./legacy-global"; const apiManagerInjectable = getInjectable({ id: "api-manager", - instantiate: () => apiManager, + instantiate: () => { + const a = apiManager; + + // NOTE: this is to remove the deprecation notice + return a; + }, }); export default apiManagerInjectable; diff --git a/src/common/k8s-api/endpoints/deployment.api.injectable.ts b/src/common/k8s-api/endpoints/deployment.api.injectable.ts new file mode 100644 index 0000000000..e4ba91a641 --- /dev/null +++ b/src/common/k8s-api/endpoints/deployment.api.injectable.ts @@ -0,0 +1,19 @@ +/** + * 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 assert from "assert"; +import { createStoresAndApisInjectionToken } from "../create-stores-apis.token"; +import { DeploymentApi } from "./deployment.api"; + +const deploymentApiInjectable = getInjectable({ + id: "deployment-api", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectionToken), "deploymentApi is only available in certain environments"); + + return new DeploymentApi(); + }, +}); + +export default deploymentApiInjectable; diff --git a/src/common/k8s-api/endpoints/deployment.api.ts b/src/common/k8s-api/endpoints/deployment.api.ts index 96b901172c..51d79572ec 100644 --- a/src/common/k8s-api/endpoints/deployment.api.ts +++ b/src/common/k8s-api/endpoints/deployment.api.ts @@ -9,7 +9,6 @@ import type { DerivedKubeApiOptions } from "../kube-api"; import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { PodMetricData, PodSpec } from "./pod.api"; -import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import type { KubeObjectScope, KubeObjectStatus, LabelSelector } from "../kube-object"; import { KubeObject } from "../kube-object"; import { hasTypedProperty, isNumber, isObject } from "../../utils"; @@ -166,7 +165,3 @@ export class Deployment extends KubeObject { - query?: { [param: string]: string | number | any }; - data?: D; // request body +export interface JsonApiParams { + data?: PartialDeep; // request body } export interface JsonApiLog { @@ -49,7 +50,16 @@ export interface JsonApiConfig { const httpAgent = new HttpAgent({ keepAlive: true }); const httpsAgent = new HttpsAgent({ keepAlive: true }); -export class JsonApi { +export type QueryParam = string | number | boolean | null | undefined | readonly string[] | readonly number[] | readonly boolean[]; +export type QueryParams = Partial>; + +export type ParamsAndQuery = ( + ValueOf extends QueryParam + ? Params & { query?: Query } + : Params & { query?: undefined } +); + +export class JsonApi = JsonApiParams> { static readonly reqInitDefault = { headers: { "content-type": "application/json", @@ -68,15 +78,15 @@ export class JsonApi { this.getRequestOptions = config.getRequestOptions ?? (() => Promise.resolve({})); } - public readonly onData = new EventEmitter<[D, Response]>(); + public readonly onData = new EventEmitter<[Data, Response]>(); public readonly onError = new EventEmitter<[JsonApiErrorParsed, Response]>(); private readonly getRequestOptions: GetRequestOptions; - get(path: string, params?: P, reqInit: RequestInit = {}) { - return this.request(path, params, { ...reqInit, method: "get" }); - } - - async getResponse(path: string, params?: P, init: RequestInit = {}): Promise { + async getResponse( + path: string, + params?: ParamsAndQuery | undefined, + init: RequestInit = {}, + ): Promise { let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`; const reqInit = merge( { @@ -87,10 +97,10 @@ export class JsonApi { await this.getRequestOptions(), init, ); - const { query } = params || {} as P; + const { query } = params ?? {}; if (query) { - const queryString = stringify(query); + const queryString = stringify(query as unknown as QueryParams); reqUrl += (reqUrl.includes("?") ? "&" : "?") + queryString; } @@ -98,23 +108,51 @@ export class JsonApi { return fetch(reqUrl, reqInit); } - post(path: string, params?: P, reqInit: RequestInit = {}) { - return this.request(path, params, { ...reqInit, method: "post" }); + get( + path: string, + params?: ParamsAndQuery | undefined, + reqInit: RequestInit = {}, + ) { + return this.request(path, params, { ...reqInit, method: "get" }); } - put(path: string, params?: P, reqInit: RequestInit = {}) { - return this.request(path, params, { ...reqInit, method: "put" }); + post( + path: string, + params?: ParamsAndQuery | undefined, + reqInit: RequestInit = {}, + ) { + return this.request(path, params, { ...reqInit, method: "post" }); } - patch(path: string, params?: P, reqInit: RequestInit = {}) { - return this.request(path, params, { ...reqInit, method: "PATCH" }); + put( + path: string, + params?: ParamsAndQuery | undefined, + reqInit: RequestInit = {}, + ) { + return this.request(path, params, { ...reqInit, method: "put" }); } - del(path: string, params?: P, reqInit: RequestInit = {}) { - return this.request(path, params, { ...reqInit, method: "delete" }); + patch( + path: string, + params?: (ParamsAndQuery, Query> & { data?: Patch | PartialDeep }) | undefined, + reqInit: RequestInit = {}, + ) { + return this.request(path, params, { ...reqInit, method: "patch" }); } - protected async request(path: string, params: P | undefined, init: Defaulted) { + del( + path: string, + params?: ParamsAndQuery | undefined, + reqInit: RequestInit = {}, + ) { + return this.request(path, params, { ...reqInit, method: "delete" }); + } + + protected async request( + path: string, + params: (ParamsAndQuery, Query> & { data?: unknown }) | undefined, + init: Defaulted, + ) { let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`; const reqInit = merge( {}, @@ -122,14 +160,14 @@ export class JsonApi { await this.getRequestOptions(), init, ); - const { data, query } = params || {} as P; + const { data, query } = params || {}; if (data && !reqInit.body) { reqInit.body = JSON.stringify(data); } if (query) { - const queryString = stringify(query); + const queryString = stringify(query as unknown as QueryParams); reqUrl += (reqUrl.includes("?") ? "&" : "?") + queryString; } @@ -141,10 +179,10 @@ export class JsonApi { const res = await fetch(reqUrl, reqInit); - return this.parseResponse(res, infoLog); + return this.parseResponse(res, infoLog); } - protected async parseResponse(res: Response, log: JsonApiLog): Promise { + protected async parseResponse(res: Response, log: JsonApiLog): Promise { const { status } = res; const text = await res.text(); diff --git a/src/common/k8s-api/kube-api-parse.ts b/src/common/k8s-api/kube-api-parse.ts index 509f1c28e9..5be50b79f6 100644 --- a/src/common/k8s-api/kube-api-parse.ts +++ b/src/common/k8s-api/kube-api-parse.ts @@ -8,11 +8,11 @@ import { splitArray } from "../utils"; export interface IKubeApiLinkRef { - apiPrefix?: string; + apiPrefix?: string | undefined; apiVersion: string; resource: string; - name?: string; - namespace?: string; + name?: string | undefined; + namespace?: string | undefined; } export interface IKubeApiParsed extends IKubeApiLinkRef { diff --git a/src/common/k8s-api/kube-api.ts b/src/common/k8s-api/kube-api.ts index cd92ef9986..47295633c8 100644 --- a/src/common/k8s-api/kube-api.ts +++ b/src/common/k8s-api/kube-api.ts @@ -105,19 +105,19 @@ export interface IgnoredKubeApiOptions { apiBase?: any; } -export interface IKubeApiQueryParams { - watch?: boolean | number; - resourceVersion?: string; - timeoutSeconds?: number; - limit?: number; // doesn't work with ?watch - continue?: string; // might be used with ?limit from second request - labelSelector?: string | string[]; // restrict list of objects by their labels, e.g. labelSelector: ["label=value"] - fieldSelector?: string | string[]; // restrict list of objects by their fields, e.g. fieldSelector: "field=name" +export interface KubeApiQueryParams { + watch?: boolean | number | undefined; + resourceVersion?: string | undefined; + timeoutSeconds?: number | undefined; + limit?: number | undefined; // doesn't work with ?watch + continue?: string | undefined; // might be used with ?limit from second request + labelSelector?: string | string[] | undefined; // restrict list of objects by their labels, e.g. labelSelector: ["label=value"] + fieldSelector?: string | string[] | undefined; // restrict list of objects by their fields, e.g. fieldSelector: "field=name" } export interface KubeApiListOptions { - namespace?: string; - reqInit?: RequestInit; + namespace?: string | undefined; + reqInit?: RequestInit | undefined; } export interface IKubePreferredVersion { @@ -126,15 +126,24 @@ export interface IKubePreferredVersion { }; } -export interface IKubeResourceList { - resources: { - kind: string; - name: string; - namespaced: boolean; - singularName: string; - storageVersionHash: string; - verbs: string[]; - }[]; +export interface KubeApiResource { + categories?: string[]; + group?: string; + kind: string; + name: string; + namespaced: boolean; + shortNames?: string[]; + singularName: string; + storageVersionHash?: string; + verbs: string[]; + version?: string; +} + +export interface KubeApiResourceList { + apiVersion?: string; + groupVersion?: string; + kind?: string; + resources: KubeApiResource[]; } export interface ILocalKubeApiConfig { @@ -288,7 +297,7 @@ export interface ResourceDescriptor { * * Note: if not provided and the resource kind is namespaced, then this defaults to `"default"` */ - namespace?: string; + namespace?: string | undefined; } export interface DeleteResourceDescriptor extends ResourceDescriptor { @@ -320,7 +329,7 @@ export class KubeApi< private watchId = 1; protected readonly doCheckPreferredVersion: boolean; protected readonly fullApiPathname: string; - protected readonly fallbackApiBases?: string[]; + protected readonly fallbackApiBases: string[] | undefined; protected readonly logger: Logger; constructor({ @@ -382,7 +391,7 @@ export class KubeApi< const { apiPrefix, apiGroup, apiVersionWithGroup, resource } = parseKubeApi(apiUrl); // Request available resources - const { resources } = await this.request.get(`${apiPrefix}/${apiVersionWithGroup}`) as IKubeResourceList; + const { resources } = (await this.request.get(`${apiPrefix}/${apiVersionWithGroup}`)) as unknown as KubeApiResourceList; // If the resource is found in the group, use this apiUrl if (resources.find(({ name }) => name === resource)) { @@ -461,7 +470,7 @@ export class KubeApi< }); } - getUrl({ name, namespace }: Partial = {}, query?: Partial) { + getUrl({ name, namespace }: Partial = {}, query?: Partial) { const resourcePath = createKubeApiURL({ apiPrefix: this.apiPrefix, apiVersion: this.apiVersionWithGroup, @@ -473,7 +482,7 @@ export class KubeApi< return resourcePath + (query ? `?${stringify(this.normalizeQuery(query))}` : ""); } - protected normalizeQuery(query: Partial = {}) { + protected normalizeQuery(query: Partial = {}) { if (query.labelSelector) { query.labelSelector = [query.labelSelector].flat().join(","); } @@ -537,7 +546,7 @@ export class KubeApi< return null; } - private ensureMetadataSelfLink(metadata: T): asserts metadata is T & { selfLink: string } { + private ensureMetadataSelfLink(metadata: T): asserts metadata is T & { selfLink: string } { metadata.selfLink ||= createKubeApiURL({ apiPrefix: this.apiPrefix, apiVersion: this.apiVersionWithGroup, @@ -547,7 +556,7 @@ export class KubeApi< }); } - async list({ namespace = "", reqInit }: KubeApiListOptions = {}, query?: IKubeApiQueryParams): Promise { + async list({ namespace = "", reqInit }: KubeApiListOptions = {}, query?: KubeApiQueryParams): Promise { await this.checkPreferredVersion(); const url = this.getUrl({ namespace }); @@ -565,7 +574,7 @@ export class KubeApi< throw new Error(`GET multiple request to ${url} returned not an array: ${JSON.stringify(parsed)}`); } - async get(desc: ResourceDescriptor, query?: IKubeApiQueryParams): Promise { + async get(desc: ResourceDescriptor, query?: KubeApiQueryParams): Promise { await this.checkPreferredVersion(); const url = this.getUrl(desc); @@ -623,7 +632,7 @@ export class KubeApi< return parsed; } - async patch(desc: ResourceDescriptor, data?: PartialDeep | Patch, strategy: KubeApiPatchType = "strategic"): Promise { + async patch(desc: ResourceDescriptor, data: PartialDeep | Patch, strategy: KubeApiPatchType = "strategic"): Promise { await this.checkPreferredVersion(); const apiUrl = this.getUrl(desc); @@ -652,7 +661,7 @@ export class KubeApi< }); } - getWatchUrl(namespace = "", query: IKubeApiQueryParams = {}) { + getWatchUrl(namespace = "", query: KubeApiQueryParams = {}) { return this.getUrl({ namespace }, { watch: 1, resourceVersion: this.getResourceVersion(namespace), diff --git a/src/common/k8s-api/kube-json-api.ts b/src/common/k8s-api/kube-json-api.ts index 0a83c67d46..2624f030c8 100644 --- a/src/common/k8s-api/kube-json-api.ts +++ b/src/common/k8s-api/kube-json-api.ts @@ -61,7 +61,11 @@ export class KubeJsonApi extends JsonApi { }); } - protected parseError(error: KubeJsonApiError | any, res: Response): string[] { + protected parseError(error: KubeJsonApiError | string, res: Response): string[] { + if (typeof error === "string") { + return [error]; + } + const { status, reason, message } = error; if (status && reason) { diff --git a/src/common/k8s-api/kube-object.store.ts b/src/common/k8s-api/kube-object.store.ts index 02e2cb8edd..3fd302163b 100644 --- a/src/common/k8s-api/kube-object.store.ts +++ b/src/common/k8s-api/kube-object.store.ts @@ -12,7 +12,7 @@ import type { KubeJsonApiDataFor, KubeObject } from "./kube-object"; import { KubeStatus } from "./kube-object"; import type { IKubeWatchEvent } from "./kube-watch-event"; import { ItemStore } from "../item.store"; -import type { IKubeApiQueryParams, KubeApi, KubeApiWatchCallback } from "./kube-api"; +import type { KubeApiQueryParams, KubeApi, KubeApiWatchCallback } from "./kube-api"; import { parseKubeApi } from "./kube-api-parse"; import type { RequestInit } from "node-fetch"; import AbortController from "abort-controller"; @@ -20,16 +20,19 @@ import type { Patch } from "rfc6902"; import logger from "../logger"; import assert from "assert"; import type { PartialDeep } from "type-fest"; +import { entries } from "../utils/objects"; + +export type OnLoadFailure = (error: unknown) => void; export interface KubeObjectStoreLoadingParams { namespaces: string[]; - reqInit?: RequestInit; + reqInit?: RequestInit | undefined; /** * A function that is called when listing fails. If set then blocks errors * being rejected with */ - onLoadFailure?: (err: any) => void; + onLoadFailure?: OnLoadFailure | undefined; } export interface KubeObjectStoreLoadAllParams { @@ -41,7 +44,7 @@ export interface KubeObjectStoreLoadAllParams { * A function that is called when listing fails. If set then blocks errors * being rejected with */ - onLoadFailure?: (err: any) => void; + onLoadFailure?: OnLoadFailure | undefined; } export interface KubeObjectStoreSubscribeParams { @@ -49,7 +52,7 @@ export interface KubeObjectStoreSubscribeParams { * A function that is called when listing fails. If set then blocks errors * being rejected with */ - onLoadFailure?: (err: any) => void; + onLoadFailure?: OnLoadFailure | undefined; /** * An optional parent abort controller @@ -88,7 +91,7 @@ export abstract class KubeObjectStore< static readonly defaultContext = observable.box(); // TODO: support multiple cluster contexts public readonly api: A; - public readonly limit?: number; + public readonly limit: number | undefined; public readonly bufferSize: number; @observable private loadedNamespaces: string[] | undefined = undefined; @@ -130,7 +133,7 @@ export abstract class KubeObjectStore< return this.contextItems.length; } - get query(): IKubeApiQueryParams { + get query(): KubeApiQueryParams { const { limit } = this; if (!limit) { @@ -170,7 +173,7 @@ export abstract class KubeObjectStore< return this.items.find(item => item.selfLink === path); } - getByLabel(labels: string[] | { [label: string]: string }): K[] { + getByLabel(labels: string[] | Partial>): K[] { if (Array.isArray(labels)) { return this.items.filter((item: K) => { const itemLabels = item.getLabels(); @@ -181,7 +184,7 @@ export abstract class KubeObjectStore< return this.items.filter((item: K) => { const itemLabels = item.metadata.labels || {}; - return Object.entries(labels) + return entries(labels) .every(([key, value]) => itemLabels[key] === value); }); } diff --git a/src/common/k8s-api/kube-object.ts b/src/common/k8s-api/kube-object.ts index 2f32b50c62..ff5ec2ae38 100644 --- a/src/common/k8s-api/kube-object.ts +++ b/src/common/k8s-api/kube-object.ts @@ -10,7 +10,6 @@ import type { KubeJsonApiData, KubeJsonApiDataList, KubeJsonApiListMetadata } fr import { autoBind, formatDuration, hasOptionalTypedProperty, hasTypedProperty, isObject, isString, isNumber, bindPredicate, isTypedArray, isRecord, json } from "../utils"; import type { ItemObject } from "../item.store"; import { apiKube } from "./index"; -import type { JsonApiParams } from "./json-api"; import * as resourceApplierApi from "./endpoints/resource-applier.api"; import type { Patch } from "rfc6902"; import assert from "assert"; @@ -653,7 +652,7 @@ export class KubeObject< /** * @deprecated use KubeApi.delete instead */ - delete(params?: JsonApiParams) { + delete(params?: object) { assert(this.selfLink, "selfLink must be present to delete self"); return apiKube.del(this.selfLink, params); diff --git a/src/common/utils/objects.ts b/src/common/utils/objects.ts index f736198c91..3554e9aab6 100644 --- a/src/common/utils/objects.ts +++ b/src/common/utils/objects.ts @@ -11,8 +11,8 @@ export function fromEntries(entries: Iterable; } +export function entries(obj: Partial> | null | undefined): [K, V][]; export function entries(obj: Record | null | undefined): [K, V][]; -export function entries(obj: Partial> | null | undefined): [K, V | undefined][]; export function entries(obj: Record | null | undefined): [K, V][] { if (obj && typeof obj == "object") { diff --git a/src/common/utils/types.ts b/src/common/utils/types.ts index 1261c04e61..1b38ddc849 100644 --- a/src/common/utils/types.ts +++ b/src/common/utils/types.ts @@ -3,10 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +export type RemoveUndefinedFromValues = { + [P in keyof K]: NonNullable; +}; + /** * This type helps define which fields of some type will always be defined */ -export type Defaulted = Required> & Omit; +export type Defaulted = RemoveUndefinedFromValues>> & Omit; export type OptionVarient = { type: Key; diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index 54837c3c89..c190863c3f 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -90,7 +90,7 @@ export type { KubeObjectStoreLoadAllParams, KubeObjectStoreLoadingParams, KubeOb export type { EventStore } from "../../renderer/components/+events/event.store"; export type { PodStore as PodsStore } from "../../renderer/components/+workloads-pods/store"; export type { NodesStore } from "../../renderer/components/+nodes/nodes.store"; -export type { DeploymentStore } from "../../renderer/components/+workloads-deployments/deployments.store"; +export type { DeploymentStore } from "../../renderer/components/+workloads-deployments/store"; export type { DaemonSetStore } from "../../renderer/components/+workloads-daemonsets/store"; export type { StatefulSetStore } from "../../renderer/components/+workloads-statefulsets/statefulset.store"; export type { JobStore } from "../../renderer/components/+workloads-jobs/job.store"; diff --git a/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.injectable.ts b/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.injectable.ts index cfd2262ab7..1dd175d838 100644 --- a/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.injectable.ts +++ b/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.injectable.ts @@ -11,7 +11,7 @@ import { MetricType, } from "./cluster-overview-store"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; -import apiManagerInjectable from "../../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; import { clusterApi } from "../../../../common/k8s-api/endpoints"; const clusterOverviewStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+custom-resources/crd.store.ts b/src/renderer/components/+custom-resources/crd.store.ts index e3a3409b83..e60bcf59da 100644 --- a/src/renderer/components/+custom-resources/crd.store.ts +++ b/src/renderer/components/+custom-resources/crd.store.ts @@ -5,7 +5,7 @@ import { computed, reaction, makeObservable } from "mobx"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { autoBind } from "../../utils"; +import { autoBind, isClusterPageContext } from "../../utils"; import type { CustomResourceDefinition, CustomResourceDefinitionApi } from "../../../common/k8s-api/endpoints/crd.api"; import { crdApi } from "../../../common/k8s-api/endpoints/crd.api"; import { apiManager } from "../../../common/k8s-api/api-manager"; @@ -70,6 +70,10 @@ export class CRDStore extends KubeObjectStore { } -export const endpointStore = new EndpointStore(endpointsApi); -apiManager.registerStore(endpointStore); +export const endpointStore = isClusterPageContext() + ? new EndpointStore(endpointsApi) + : undefined as never; + +if (isClusterPageContext()) { + apiManager.registerStore(endpointStore); +} diff --git a/src/renderer/components/+nodes/nodes.store.ts b/src/renderer/components/+nodes/nodes.store.ts index b9b04dbf80..e3807df85d 100644 --- a/src/renderer/components/+nodes/nodes.store.ts +++ b/src/renderer/components/+nodes/nodes.store.ts @@ -9,7 +9,7 @@ import { apiManager } from "../../../common/k8s-api/api-manager"; import type { Node, NodeApi } from "../../../common/k8s-api/endpoints"; import { nodeApi } from "../../../common/k8s-api/endpoints"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { autoBind } from "../../utils"; +import { autoBind, isClusterPageContext } from "../../utils"; export class NodesStore extends KubeObjectStore { constructor() { @@ -32,5 +32,10 @@ export class NodesStore extends KubeObjectStore { } } -export const nodesStore = new NodesStore(); -apiManager.registerStore(nodesStore); +export const nodesStore = isClusterPageContext() + ? new NodesStore() + : undefined as never; + +if (isClusterPageContext()) { + apiManager.registerStore(nodesStore); +} diff --git a/src/renderer/components/+user-management/+cluster-role-bindings/store.injectable.ts b/src/renderer/components/+user-management/+cluster-role-bindings/store.injectable.ts index 924ba76f7e..c10285662a 100644 --- a/src/renderer/components/+user-management/+cluster-role-bindings/store.injectable.ts +++ b/src/renderer/components/+user-management/+cluster-role-bindings/store.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import assert from "assert"; import { createStoresAndApisInjectionToken } from "../../../../common/k8s-api/create-stores-apis.token"; import clusterRoleBindingApiInjectable from "../../../../common/k8s-api/endpoints/cluster-role-binding.api.injectable"; -import apiManagerInjectable from "../../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; import { ClusterRoleBindingStore } from "./store"; const clusterRoleBindingStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+user-management/+cluster-roles/store.injectable.ts b/src/renderer/components/+user-management/+cluster-roles/store.injectable.ts index b6b6083cce..e106b213a4 100644 --- a/src/renderer/components/+user-management/+cluster-roles/store.injectable.ts +++ b/src/renderer/components/+user-management/+cluster-roles/store.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import assert from "assert"; import { createStoresAndApisInjectionToken } from "../../../../common/k8s-api/create-stores-apis.token"; import clusterRoleApiInjectable from "../../../../common/k8s-api/endpoints/cluster-role.api.injectable"; -import apiManagerInjectable from "../../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; import { ClusterRolesStore } from "./store"; const clusterRoleStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+user-management/+roles/store.injectable.ts b/src/renderer/components/+user-management/+roles/store.injectable.ts index 803edc00a2..be5274c41e 100644 --- a/src/renderer/components/+user-management/+roles/store.injectable.ts +++ b/src/renderer/components/+user-management/+roles/store.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import assert from "assert"; import roleApiInjectable from "../../../../common/k8s-api/endpoints/role.api.injectable"; import createStoresAndApisInjectable from "../../../create-stores-apis.injectable"; -import apiManagerInjectable from "../../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; import { RoleStore } from "./store"; const roleStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+user-management/+service-accounts/store.injectable.ts b/src/renderer/components/+user-management/+service-accounts/store.injectable.ts index f9e7835afa..c35ccb6405 100644 --- a/src/renderer/components/+user-management/+service-accounts/store.injectable.ts +++ b/src/renderer/components/+user-management/+service-accounts/store.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import assert from "assert"; import serviceAccountApiInjectable from "../../../../common/k8s-api/endpoints/service-account.api.injectable"; import createStoresAndApisInjectable from "../../../create-stores-apis.injectable"; -import apiManagerInjectable from "../../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; import { ServiceAccountStore } from "./store"; const serviceAccountStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+workloads-daemonsets/store.injectable.ts b/src/renderer/components/+workloads-daemonsets/store.injectable.ts index d9dcf4459d..4ba99694a7 100644 --- a/src/renderer/components/+workloads-daemonsets/store.injectable.ts +++ b/src/renderer/components/+workloads-daemonsets/store.injectable.ts @@ -7,7 +7,7 @@ import assert from "assert"; import getPodsByOwnerIdInjectable from "../+workloads-pods/get-pods-by-owner-id.injectable"; import daemonSetApiInjectable from "../../../common/k8s-api/endpoints/daemon-set.api.injectable"; import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; -import apiManagerInjectable from "../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import { DaemonSetStore } from "./store"; const daemonSetStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+workloads-deployments/deployment-details.tsx b/src/renderer/components/+workloads-deployments/deployment-details.tsx index b04e8ebf38..aade93362d 100644 --- a/src/renderer/components/+workloads-deployments/deployment-details.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-details.tsx @@ -16,7 +16,7 @@ import { PodDetailsTolerations } from "../+workloads-pods/pod-details-toleration import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics"; -import { deploymentStore } from "./deployments.store"; +import type { DeploymentStore } from "./store"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { makeObservable, observable, reaction } from "mobx"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; @@ -32,6 +32,7 @@ import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.inj import type { PodStore } from "../+workloads-pods/store"; import podStoreInjectable from "../+workloads-pods/store.injectable"; import replicaSetStoreInjectable from "../+workloads-replicasets/store.injectable"; +import deploymentStoreInjectable from "./store.injectable"; export interface DeploymentDetailsProps extends KubeObjectDetailsProps { } @@ -40,6 +41,7 @@ interface Dependencies { subscribeStores: SubscribeStores; podStore: PodStore; replicaSetStore: ReplicaSetStore; + deploymentStore: DeploymentStore; } @observer @@ -71,7 +73,7 @@ class NonInjectedDeploymentDetails extends React.Component deploymentStore, - causesSideEffects: true, -}); - -export default deploymentsStoreInjectable; diff --git a/src/renderer/components/+workloads-deployments/deployments.store.ts b/src/renderer/components/+workloads-deployments/deployments.store.ts deleted file mode 100644 index 2351e68225..0000000000 --- a/src/renderer/components/+workloads-deployments/deployments.store.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { podStore } from "../+workloads-pods/legacy-store"; -import { apiManager } from "../../../common/k8s-api/api-manager"; -import type { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints"; -import { deploymentApi, PodStatusPhase } from "../../../common/k8s-api/endpoints"; -import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { isClusterPageContext } from "../../utils"; - -export class DeploymentStore extends KubeObjectStore { - protected sortItems(items: Deployment[]) { - return super.sortItems(items, [ - item => item.getReplicas(), - ], "desc"); - } - - getStatuses(deployments?: Deployment[]) { - const status = { running: 0, failed: 0, pending: 0 }; - - deployments?.forEach(deployment => { - const pods = this.getChildPods(deployment); - - if (pods.some(pod => pod.getStatus() === PodStatusPhase.FAILED)) { - status.failed++; - } - else if (pods.some(pod => pod.getStatus() === PodStatusPhase.PENDING)) { - status.pending++; - } - else { - status.running++; - } - }); - - return status; - } - - getChildPods(deployment: Deployment) { - return podStore - .getByLabel(deployment.getTemplateLabels()) - .filter(pod => pod.getNs() === deployment.getNs()); - } -} - -export const deploymentStore = isClusterPageContext() - ? new DeploymentStore(deploymentApi) - : undefined as never; - -if (isClusterPageContext()) { - apiManager.registerStore(deploymentStore); -} diff --git a/src/renderer/components/+workloads-deployments/deployments.tsx b/src/renderer/components/+workloads-deployments/deployments.tsx index 4d9082f3e4..e8b28a2e6f 100644 --- a/src/renderer/components/+workloads-deployments/deployments.tsx +++ b/src/renderer/components/+workloads-deployments/deployments.tsx @@ -8,7 +8,7 @@ import "./deployments.scss"; import React from "react"; import { observer } from "mobx-react"; import type { Deployment } from "../../../common/k8s-api/endpoints"; -import { deploymentStore } from "./deployments.store"; +import { deploymentStore } from "./legacy-store"; import { eventStore } from "../+events/event.store"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { cssNames } from "../../utils"; diff --git a/src/renderer/components/+workloads-deployments/legacy-store.ts b/src/renderer/components/+workloads-deployments/legacy-store.ts new file mode 100644 index 0000000000..f7d629729b --- /dev/null +++ b/src/renderer/components/+workloads-deployments/legacy-store.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; +import deploymentStoreInjectable from "./store.injectable"; + +/** + * @deprecated use `di.inject(deploymentStoreInjectable)` instead + */ +export const deploymentStore = asLegacyGlobalForExtensionApi(deploymentStoreInjectable); diff --git a/src/renderer/components/+workloads-deployments/store.injectable.ts b/src/renderer/components/+workloads-deployments/store.injectable.ts new file mode 100644 index 0000000000..a61b3666fd --- /dev/null +++ b/src/renderer/components/+workloads-deployments/store.injectable.ts @@ -0,0 +1,30 @@ +/** + * 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 assert from "assert"; +import podStoreInjectable from "../+workloads-pods/store.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; +import { createStoresAndApisInjectionToken } from "../../../common/k8s-api/create-stores-apis.token"; +import deploymentApiInjectable from "../../../common/k8s-api/endpoints/deployment.api.injectable"; +import { DeploymentStore } from "./store"; + +const deploymentStoreInjectable = getInjectable({ + id: "deployment-store", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectionToken), "deploymentStore is only available in certain environments"); + + const api = di.inject(deploymentApiInjectable); + const apiManager = di.inject(apiManagerInjectable); + const store = new DeploymentStore({ + podStore: di.inject(podStoreInjectable), + }, api); + + apiManager.registerStore(store); + + return store; + }, +}); + +export default deploymentStoreInjectable; diff --git a/src/renderer/components/+workloads-deployments/store.ts b/src/renderer/components/+workloads-deployments/store.ts new file mode 100644 index 0000000000..014f1c2abc --- /dev/null +++ b/src/renderer/components/+workloads-deployments/store.ts @@ -0,0 +1,63 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { PodStore } from "../+workloads-pods/store"; +import type { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints"; +import { PodStatusPhase } from "../../../common/k8s-api/endpoints"; +import type { KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; +import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; + +// This needs to be disables because of https://github.com/microsoft/TypeScript/issues/15300 +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type DeploymentStatuses = { + running: number; + failed: number; + pending: number; +}; + +export interface DeploymentStoreDependencies { + readonly podStore: PodStore; +} + +export class DeploymentStore extends KubeObjectStore { + constructor(protected readonly dependencies: DeploymentStoreDependencies, api: DeploymentApi, opts?: KubeObjectStoreOptions) { + super(api, opts); + } + + protected sortItems(items: Deployment[]) { + return super.sortItems(items, [ + item => item.getReplicas(), + ], "desc"); + } + + getStatuses(deployments: Deployment[]): DeploymentStatuses; + /** + * @deprecated + */ + getStatuses(deployments: Deployment[] | undefined): DeploymentStatuses; + getStatuses(deployments: Deployment[] = []) { + const status = { running: 0, failed: 0, pending: 0 }; + + deployments.forEach(deployment => { + const statuses = new Set(this.getChildPods(deployment).map(pod => pod.getStatus())); + + if (statuses.has(PodStatusPhase.FAILED)) { + status.failed++; + } else if (statuses.has(PodStatusPhase.PENDING)) { + status.pending++; + } else { + status.running++; + } + }); + + return status; + } + + getChildPods(deployment: Deployment) { + return this.dependencies.podStore + .getByLabel(deployment.getTemplateLabels()) + .filter(pod => pod.getNs() === deployment.getNs()); + } +} diff --git a/src/renderer/components/+workloads-overview/overview.tsx b/src/renderer/components/+workloads-overview/overview.tsx index a332659dcd..fa028b962f 100644 --- a/src/renderer/components/+workloads-overview/overview.tsx +++ b/src/renderer/components/+workloads-overview/overview.tsx @@ -8,7 +8,7 @@ import "./overview.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { eventStore } from "../+events/event.store"; -import { deploymentStore } from "../+workloads-deployments/deployments.store"; +import { deploymentStore } from "../+workloads-deployments/store"; import { statefulSetStore } from "../+workloads-statefulsets/statefulset.store"; import { jobStore } from "../+workloads-jobs/job.store"; import { cronJobStore } from "../+workloads-cronjobs/cronjob.store"; diff --git a/src/renderer/components/+workloads-overview/workloads/implementations/deployments-workload.injectable.ts b/src/renderer/components/+workloads-overview/workloads/implementations/deployments-workload.injectable.ts index 8bd680a88e..f75537e0b7 100644 --- a/src/renderer/components/+workloads-overview/workloads/implementations/deployments-workload.injectable.ts +++ b/src/renderer/components/+workloads-overview/workloads/implementations/deployments-workload.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { workloadInjectionToken } from "../workload-injection-token"; import { ResourceNames } from "../../../../utils/rbac"; import namespaceStoreInjectable from "../../../+namespaces/namespace-store/namespace-store.injectable"; -import deploymentsStoreInjectable from "../../../+workloads-deployments/deployments-store.injectable"; +import deploymentsStoreInjectable from "../../../+workloads-deployments/store.injectable"; import navigateToDeploymentsInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/deployments/navigate-to-deployments.injectable"; import { computed } from "mobx"; diff --git a/src/renderer/components/+workloads-overview/workloads/workload-injection-token.ts b/src/renderer/components/+workloads-overview/workloads/workload-injection-token.ts index 6e7bfcd74a..6453efe59b 100644 --- a/src/renderer/components/+workloads-overview/workloads/workload-injection-token.ts +++ b/src/renderer/components/+workloads-overview/workloads/workload-injection-token.ts @@ -9,7 +9,7 @@ export interface Workload { resourceName: string; open: () => void; amountOfItems: IComputedValue; - status: IComputedValue>; + status: IComputedValue>>; title: string; orderNumber: number; } diff --git a/src/renderer/components/+workloads-pods/details/volumes/variant-helpers.tsx b/src/renderer/components/+workloads-pods/details/volumes/variant-helpers.tsx index 55f2bf19d6..127f78cdcc 100644 --- a/src/renderer/components/+workloads-pods/details/volumes/variant-helpers.tsx +++ b/src/renderer/components/+workloads-pods/details/volumes/variant-helpers.tsx @@ -5,7 +5,7 @@ import React from "react"; import { Link } from "react-router-dom"; import type { PodVolumeVariants, Pod, SecretReference } from "../../../../../common/k8s-api/endpoints"; -import type { IKubeApiQueryParams, ResourceDescriptor } from "../../../../../common/k8s-api/kube-api"; +import type { KubeApiQueryParams, ResourceDescriptor } from "../../../../../common/k8s-api/kube-api"; import type { LocalObjectReference } from "../../../../../common/k8s-api/kube-object"; import { DrawerItem } from "../../../drawer"; import { getDetailsUrl } from "../../../kube-detail-params"; @@ -19,7 +19,7 @@ export interface PodVolumeVariantSpecificProps = React.FunctionComponent>; export interface LocalRefPropsApi { - getUrl(desc?: Partial, query?: Partial): string; + getUrl(desc?: Partial, query?: Partial): string; } export interface LocalRefProps { diff --git a/src/renderer/components/+workloads-pods/store.injectable.ts b/src/renderer/components/+workloads-pods/store.injectable.ts index bc9909e09a..d6fb50968d 100644 --- a/src/renderer/components/+workloads-pods/store.injectable.ts +++ b/src/renderer/components/+workloads-pods/store.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import assert from "assert"; import podApiInjectable from "../../../common/k8s-api/endpoints/pod.api.injectable"; import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; -import apiManagerInjectable from "../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import { PodStore } from "./store"; const podStoreInjectable = getInjectable({ diff --git a/src/renderer/components/+workloads-replicasets/store.injectable.ts b/src/renderer/components/+workloads-replicasets/store.injectable.ts index 863678545e..60be500d4f 100644 --- a/src/renderer/components/+workloads-replicasets/store.injectable.ts +++ b/src/renderer/components/+workloads-replicasets/store.injectable.ts @@ -7,7 +7,7 @@ import assert from "assert"; import getPodsByOwnerIdInjectable from "../+workloads-pods/get-pods-by-owner-id.injectable"; import replicaSetApiInjectable from "../../../common/k8s-api/endpoints/replica-set.api.injectable"; import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; -import apiManagerInjectable from "../kube-object-menu/dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import { ReplicaSetStore } from "./store"; const replicaSetStoreInjectable = getInjectable({ diff --git a/src/renderer/components/__tests__/deployments.store.test.ts b/src/renderer/components/__tests__/deployments.store.test.ts index 2a0d364de7..1b347d85f6 100644 --- a/src/renderer/components/__tests__/deployments.store.test.ts +++ b/src/renderer/components/__tests__/deployments.store.test.ts @@ -4,10 +4,13 @@ */ import { observable } from "mobx"; -import { deploymentStore } from "../+workloads-deployments/deployments.store"; -import { podStore } from "../+workloads-pods/legacy-store"; +import type { DeploymentStore } from "../+workloads-deployments/store"; +import deploymentStoreInjectable from "../+workloads-deployments/store.injectable"; +import podStoreInjectable from "../+workloads-pods/store.injectable"; import type { PodSpec } from "../../../common/k8s-api/endpoints"; import { Deployment, Pod } from "../../../common/k8s-api/endpoints"; +import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; const spec: PodSpec = { containers: [{ @@ -200,13 +203,22 @@ const failedPod = new Pod({ }); describe("Deployment Store tests", () => { - beforeAll(() => { + let deploymentStore: DeploymentStore; + + beforeEach(() => { + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + di.override(createStoresAndApisInjectable, () => true); + + const podStore = di.inject(podStoreInjectable); + // Add pods to pod store podStore.items = observable.array([ runningPod, failedPod, pendingPod, ]); + deploymentStore = di.inject(deploymentStoreInjectable); }); it("gets Deployment statuses in proper sorting order", () => { diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx index 98f15d0701..d3b9435022 100644 --- a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx +++ b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx @@ -19,7 +19,7 @@ import type { DiRender } from "../test-utils/renderFor"; import { renderFor } from "../test-utils/renderFor"; import type { Cluster } from "../../../common/cluster/cluster"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; -import apiManagerInjectable from "./dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import { KubeObjectMenu } from "./index"; import type { KubeObjectMenuRegistration } from "./dependencies/kube-object-menu-items/kube-object-menu-registration"; import { computed } from "mobx"; diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.tsx index 46a6bbea43..60324bc8e0 100644 --- a/src/renderer/components/kube-object-menu/kube-object-menu.tsx +++ b/src/renderer/components/kube-object-menu/kube-object-menu.tsx @@ -15,7 +15,7 @@ import clusterNameInjectable from "./dependencies/cluster-name.injectable"; import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; import hideDetailsInjectable from "./dependencies/hide-details.injectable"; import kubeObjectMenuItemsInjectable from "./dependencies/kube-object-menu-items/kube-object-menu-items.injectable"; -import apiManagerInjectable from "./dependencies/api-manager.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; export interface KubeObjectMenuProps extends MenuActionsProps { object: TKubeObject;