diff --git a/src/common/k8s-api/endpoints/legacy-globals.ts b/src/common/k8s-api/endpoints/legacy-globals.ts index 72784b5a46..3938e1331f 100644 --- a/src/common/k8s-api/endpoints/legacy-globals.ts +++ b/src/common/k8s-api/endpoints/legacy-globals.ts @@ -8,6 +8,7 @@ import clusterRoleBindingApiInjectable from "./cluster-role-binding.api.injectab import clusterRoleApiInjectable from "./cluster-role.api.injectable"; import daemonSetApiInjectable from "./daemon-set.api.injectable"; import podApiInjectable from "./pod.api.injectable"; +import replicaSetApiInjectable from "./replica-set.api.injectable"; import roleApiInjectable from "./role.api.injectable"; import serviceAccountApiInjectable from "./service-account.api.injectable"; @@ -40,3 +41,8 @@ export const podApi = asLegacyGlobalForExtensionApi(podApiInjectable); * @deprecated use `di.inject(daemonSetApiInjectable)` instead */ export const daemonSetApi = asLegacyGlobalForExtensionApi(daemonSetApiInjectable); + +/** + * @deprecated use `di.inject(replicaSetApiInjectable)` instead + */ +export const replicaSetApi = asLegacyGlobalForExtensionApi(replicaSetApiInjectable); diff --git a/src/common/k8s-api/endpoints/replica-set.api.injectable.ts b/src/common/k8s-api/endpoints/replica-set.api.injectable.ts new file mode 100644 index 0000000000..9c654fd743 --- /dev/null +++ b/src/common/k8s-api/endpoints/replica-set.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 { ReplicaSetApi } from "./replica-set.api"; + +const replicaSetApiInjectable = getInjectable({ + id: "replica-set-api", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectionToken), "replicaSetApi is only available in certain environments"); + + return new ReplicaSetApi(); + }, +}); + +export default replicaSetApiInjectable; diff --git a/src/common/k8s-api/endpoints/replica-set.api.ts b/src/common/k8s-api/endpoints/replica-set.api.ts index cf4be35f98..2ad571d4e9 100644 --- a/src/common/k8s-api/endpoints/replica-set.api.ts +++ b/src/common/k8s-api/endpoints/replica-set.api.ts @@ -7,7 +7,6 @@ import type { DerivedKubeApiOptions, IgnoredKubeApiOptions } from "../kube-api"; import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { PodMetricData } 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 type { PodTemplateSpec } from "./types/pod-template-spec"; @@ -121,7 +120,3 @@ export class ReplicaSet extends KubeObject container.image); } } - -export const replicaSetApi = isClusterPageContext() - ? new ReplicaSetApi() - : undefined as never; diff --git a/src/extensions/main-api/k8s-api.ts b/src/extensions/main-api/k8s-api.ts index bee8371363..7f95f77bf0 100644 --- a/src/extensions/main-api/k8s-api.ts +++ b/src/extensions/main-api/k8s-api.ts @@ -7,6 +7,7 @@ import clusterRoleBindingApiInjectable from "../../common/k8s-api/endpoints/clus import clusterRoleApiInjectable from "../../common/k8s-api/endpoints/cluster-role.api.injectable"; import daemonSetApiInjectable from "../../common/k8s-api/endpoints/daemon-set.api.injectable"; import podApiInjectable from "../../common/k8s-api/endpoints/pod.api.injectable"; +import replicaSetApiInjectable from "../../common/k8s-api/endpoints/replica-set.api.injectable"; import roleApiInjectable from "../../common/k8s-api/endpoints/role.api.injectable"; import serviceAccountApiInjectable from "../../common/k8s-api/endpoints/service-account.api.injectable"; import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; @@ -25,6 +26,7 @@ export const clusterRoleBindingApi = asLegacyGlobalForExtensionApi(clusterRoleBi export const roleApi = asLegacyGlobalForExtensionApi(roleApiInjectable); export const podsApi = asLegacyGlobalForExtensionApi(podApiInjectable); export const daemonSetApi = asLegacyGlobalForExtensionApi(daemonSetApiInjectable); +export const replicaSetApi = asLegacyGlobalForExtensionApi(replicaSetApiInjectable); export { ResourceStack } from "../../common/k8s/resource-stack"; export { apiManager } from "../../common/k8s-api/api-manager"; @@ -40,7 +42,7 @@ export { Job, jobApi } from "../../common/k8s-api/endpoints/job.api"; export { CronJob, cronJobApi } from "../../common/k8s-api/endpoints/cron-job.api"; export { ConfigMap, configMapApi } from "../../common/k8s-api/endpoints/configmap.api"; export { Secret, secretApi as secretsApi } from "../../common/k8s-api/endpoints/secret.api"; -export { ReplicaSet, replicaSetApi } from "../../common/k8s-api/endpoints/replica-set.api"; +export { ReplicaSet } from "../../common/k8s-api/endpoints/replica-set.api"; export { ResourceQuota, resourceQuotaApi } from "../../common/k8s-api/endpoints/resource-quota.api"; export { LimitRange, limitRangeApi } from "../../common/k8s-api/endpoints/limit-range.api"; export { HorizontalPodAutoscaler, horizontalPodAutoscalerApi as hpaApi } from "../../common/k8s-api/endpoints/hpa.api"; diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index 683703286d..eff7087b49 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -14,6 +14,7 @@ import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extensio import roleApiInjectable from "../../common/k8s-api/endpoints/role.api.injectable"; import podApiInjectable from "../../common/k8s-api/endpoints/pod.api.injectable"; import daemonSetApiInjectable from "../../common/k8s-api/endpoints/daemon-set.api.injectable"; +import replicaSetApiInjectable from "../../common/k8s-api/endpoints/replica-set.api.injectable"; export function isAllowedResource(resource: KubeResource | KubeResource[]) { const resources = castArray(resource); @@ -34,6 +35,7 @@ export const clusterRoleBindingApi = asLegacyGlobalForExtensionApi(clusterRoleBi export const roleApi = asLegacyGlobalForExtensionApi(roleApiInjectable); export const podsApi = asLegacyGlobalForExtensionApi(podApiInjectable); export const daemonSetApi = asLegacyGlobalForExtensionApi(daemonSetApiInjectable); +export const replicaSetApi = asLegacyGlobalForExtensionApi(replicaSetApiInjectable); export { BaseKubeJsonApiObjectMetadata, @@ -52,7 +54,7 @@ export { Job, jobApi } from "../../common/k8s-api/endpoints/job.api"; export { CronJob, cronJobApi } from "../../common/k8s-api/endpoints/cron-job.api"; export { ConfigMap, configMapApi } from "../../common/k8s-api/endpoints/configmap.api"; export { Secret, secretApi as secretsApi } from "../../common/k8s-api/endpoints/secret.api"; -export { ReplicaSet, replicaSetApi } from "../../common/k8s-api/endpoints/replica-set.api"; +export { ReplicaSet } from "../../common/k8s-api/endpoints/replica-set.api"; export { ResourceQuota, resourceQuotaApi } from "../../common/k8s-api/endpoints/resource-quota.api"; export { LimitRange, limitRangeApi } from "../../common/k8s-api/endpoints/limit-range.api"; export { HorizontalPodAutoscaler, horizontalPodAutoscalerApi as hpaApi } from "../../common/k8s-api/endpoints/hpa.api"; @@ -93,7 +95,7 @@ export type { JobStore } from "../../renderer/components/+workloads-jobs/job.sto export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/cronjob.store"; export type { ConfigMapStore as ConfigMapsStore } from "../../renderer/components/+config-maps/config-maps.store"; export type { SecretStore as SecretsStore } from "../../renderer/components/+config-secrets/secrets.store"; -export type { ReplicaSetStore } from "../../renderer/components/+workloads-replicasets/replicasets.store"; +export type { ReplicaSetStore } from "../../renderer/components/+workloads-replicasets/store"; export type { ResourceQuotaStore as ResourceQuotasStore } from "../../renderer/components/+config-resource-quotas/resource-quotas.store"; export type { LimitRangeStore as LimitRangesStore } from "../../renderer/components/+config-limit-ranges/limit-ranges.store"; export type { HorizontalPodAutoscalerStore as HPAStore } from "../../renderer/components/+config-autoscalers/hpa.store"; diff --git a/src/renderer/components/+workloads-deployments/deployment-details.tsx b/src/renderer/components/+workloads-deployments/deployment-details.tsx index 4cbcd4880c..b04e8ebf38 100644 --- a/src/renderer/components/+workloads-deployments/deployment-details.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-details.tsx @@ -21,7 +21,7 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { makeObservable, observable, reaction } from "mobx"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { KubeObjectMeta } from "../kube-object-meta"; -import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; +import type { ReplicaSetStore } from "../+workloads-replicasets/store"; import { DeploymentReplicaSets } from "./deployment-replicasets"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; @@ -31,6 +31,7 @@ import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import type { PodStore } from "../+workloads-pods/store"; import podStoreInjectable from "../+workloads-pods/store.injectable"; +import replicaSetStoreInjectable from "../+workloads-replicasets/store.injectable"; export interface DeploymentDetailsProps extends KubeObjectDetailsProps { } @@ -38,6 +39,7 @@ export interface DeploymentDetailsProps extends KubeObjectDetailsProps[]>; @@ -36,6 +37,7 @@ interface Dependencies { subscribeStores: SubscribeStores; podStore: PodStore; daemonSetStore: DaemonSetStore; + replicaSetStore: ReplicaSetStore; } @observer @@ -56,7 +58,7 @@ class NonInjectedWorkloadsOverview extends React.Component { eventStore, jobStore, this.props.podStore, - replicaSetStore, + this.props.replicaSetStore, statefulSetStore, ], { onLoadFailure: error => this.loadErrors.push(String(error)), @@ -115,5 +117,6 @@ export const WorkloadsOverview = withInjectables(NonInjectedWorklo subscribeStores: di.inject(subscribeStoresInjectable), daemonSetStore: di.inject(daemonSetStoreInjectable), podStore: di.inject(podStoreInjectable), + replicaSetStore: di.inject(replicaSetStoreInjectable), }), }); diff --git a/src/renderer/components/+workloads-overview/workloads/implementations/replicasets-workload.injectable.ts b/src/renderer/components/+workloads-overview/workloads/implementations/replicasets-workload.injectable.ts index 71eed58284..f8cc629ce0 100644 --- a/src/renderer/components/+workloads-overview/workloads/implementations/replicasets-workload.injectable.ts +++ b/src/renderer/components/+workloads-overview/workloads/implementations/replicasets-workload.injectable.ts @@ -7,7 +7,7 @@ import { workloadInjectionToken } from "../workload-injection-token"; import { ResourceNames } from "../../../../utils/rbac"; import navigateToPodsInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/deployments/navigate-to-deployments.injectable"; import namespaceStoreInjectable from "../../../+namespaces/namespace-store/namespace-store.injectable"; -import replicasetsStoreInjectable from "../../../+workloads-replicasets/replicasets-store.injectable"; +import replicasetsStoreInjectable from "../../../+workloads-replicasets/store.injectable"; import { computed } from "mobx"; const replicasetsWorkloadInjectable = getInjectable({ diff --git a/src/renderer/components/+workloads-replicasets/legacy-store.ts b/src/renderer/components/+workloads-replicasets/legacy-store.ts new file mode 100644 index 0000000000..ac835163d4 --- /dev/null +++ b/src/renderer/components/+workloads-replicasets/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 replicaSetStoreInjectable from "./store.injectable"; + +/** + * @deprecated use `di.inject(replicaSetStoreInjectable)` instead + */ +export const replicaSetStore = asLegacyGlobalForExtensionApi(replicaSetStoreInjectable); diff --git a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx index cc64682436..b4d35c1617 100644 --- a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx +++ b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx @@ -8,7 +8,6 @@ import React from "react"; import { makeObservable, observable, reaction } from "mobx"; import { DrawerItem } from "../drawer"; import { Badge } from "../badge"; -import { replicaSetStore } from "./replicasets.store"; import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses"; import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations"; import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; @@ -28,6 +27,8 @@ import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import type { PodStore } from "../+workloads-pods/store"; import podStoreInjectable from "../+workloads-pods/store.injectable"; +import type { ReplicaSetStore } from "./store"; +import replicaSetStoreInjectable from "./store.injectable"; export interface ReplicaSetDetailsProps extends KubeObjectDetailsProps { } @@ -35,6 +36,7 @@ export interface ReplicaSetDetailsProps extends KubeObjectDetailsProps replicaSetStore, - causesSideEffects: true, -}); - -export default replicasetsStoreInjectable; diff --git a/src/renderer/components/+workloads-replicasets/replicasets.tsx b/src/renderer/components/+workloads-replicasets/replicasets.tsx index 7caa666c49..45344951f5 100644 --- a/src/renderer/components/+workloads-replicasets/replicasets.tsx +++ b/src/renderer/components/+workloads-replicasets/replicasets.tsx @@ -7,7 +7,7 @@ import "./replicasets.scss"; import React from "react"; import { observer } from "mobx-react"; -import { replicaSetStore } from "./replicasets.store"; +import { replicaSetStore } from "./legacy-store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { eventStore } from "../+events/event.store"; diff --git a/src/renderer/components/+workloads-replicasets/store.injectable.ts b/src/renderer/components/+workloads-replicasets/store.injectable.ts new file mode 100644 index 0000000000..863678545e --- /dev/null +++ b/src/renderer/components/+workloads-replicasets/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 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 { ReplicaSetStore } from "./store"; + +const replicaSetStoreInjectable = getInjectable({ + id: "replica-set-store", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectable), "replicaSetStore is only available in certain environments"); + + const api = di.inject(replicaSetApiInjectable); + const apiManager = di.inject(apiManagerInjectable); + const store = new ReplicaSetStore({ + getPodsByOwnerId: di.inject(getPodsByOwnerIdInjectable), + }, api); + + apiManager.registerStore(store); + + return store; + }, +}); + +export default replicaSetStoreInjectable; diff --git a/src/renderer/components/+workloads-replicasets/replicasets.store.ts b/src/renderer/components/+workloads-replicasets/store.ts similarity index 70% rename from src/renderer/components/+workloads-replicasets/replicasets.store.ts rename to src/renderer/components/+workloads-replicasets/store.ts index cba5a2779a..6db50809f4 100644 --- a/src/renderer/components/+workloads-replicasets/replicasets.store.ts +++ b/src/renderer/components/+workloads-replicasets/store.ts @@ -3,17 +3,23 @@ * 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 { GetPodsByOwnerId } from "../+workloads-pods/get-pods-by-owner-id.injectable"; import type { Deployment, ReplicaSet, ReplicaSetApi } from "../../../common/k8s-api/endpoints"; -import { replicaSetApi } from "../../../common/k8s-api/endpoints"; import { PodStatusPhase } from "../../../common/k8s-api/endpoints/pod.api"; +import type { KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { isClusterPageContext } from "../../utils"; + +export interface ReplicaSetStoreDependencies { + getPodsByOwnerId: GetPodsByOwnerId; +} export class ReplicaSetStore extends KubeObjectStore { + constructor(protected readonly dependencies: ReplicaSetStoreDependencies, api: ReplicaSetApi, opts?: KubeObjectStoreOptions) { + super(api, opts); + } + getChildPods(replicaSet: ReplicaSet) { - return podStore.getPodsByOwnerId(replicaSet.getId()); + return this.dependencies.getPodsByOwnerId(replicaSet.getId()); } getStatuses(replicaSets: ReplicaSet[]) { @@ -40,11 +46,3 @@ export class ReplicaSetStore extends KubeObjectStore ); } } - -export const replicaSetStore = isClusterPageContext() - ? new ReplicaSetStore(replicaSetApi) - : undefined as never; - -if (isClusterPageContext()) { - apiManager.registerStore(replicaSetStore); -} diff --git a/src/renderer/components/__tests__/daemonset.store.test.ts b/src/renderer/components/__tests__/daemonset.store.test.ts index 22c0b4e60e..13ee0a0891 100644 --- a/src/renderer/components/__tests__/daemonset.store.test.ts +++ b/src/renderer/components/__tests__/daemonset.store.test.ts @@ -133,7 +133,7 @@ const failedPod = new Pod({ describe("DaemonSet Store tests", () => { let daemonSetStore: DaemonSetStore; - beforeAll(() => { + beforeEach(() => { const di = getDiForUnitTesting({ doGeneralOverrides: true }); di.override(createStoresAndApisInjectable, () => true); diff --git a/src/renderer/components/__tests__/replicaset.store.test.ts b/src/renderer/components/__tests__/replicaset.store.test.ts index 9dc5c698ea..b1895e93b7 100644 --- a/src/renderer/components/__tests__/replicaset.store.test.ts +++ b/src/renderer/components/__tests__/replicaset.store.test.ts @@ -4,9 +4,12 @@ */ import { observable } from "mobx"; -import { podStore } from "../+workloads-pods/legacy-store"; -import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; +import podStoreInjectable from "../+workloads-pods/store.injectable"; +import replicasetsStoreInjectable from "../+workloads-replicasets/store.injectable"; +import type { ReplicaSetStore } from "../+workloads-replicasets/store"; import { ReplicaSet, Pod } from "../../../common/k8s-api/endpoints"; +import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; const runningReplicaSet = new ReplicaSet({ apiVersion: "foo", @@ -128,7 +131,16 @@ const failedPod = new Pod({ }); describe("ReplicaSet Store tests", () => { - beforeAll(() => { + let replicaSetStore: ReplicaSetStore; + + beforeEach(() => { + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + di.override(createStoresAndApisInjectable, () => true); + + const podStore = di.inject(podStoreInjectable); + + replicaSetStore = di.inject(replicasetsStoreInjectable); podStore.items = observable.array([ runningPod, failedPod,