diff --git a/src/common/k8s-api/endpoints/cron-job.api.injectable.ts b/src/common/k8s-api/endpoints/cron-job.api.injectable.ts new file mode 100644 index 0000000000..1fda23e42e --- /dev/null +++ b/src/common/k8s-api/endpoints/cron-job.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 { CronJobApi } from "./cron-job.api"; + +const cronJobApiInjectable = getInjectable({ + id: "cron-job-api", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectionToken), "cronJobApi is only available in certain environments"); + + return new CronJobApi(); + }, +}); + +export default cronJobApiInjectable; diff --git a/src/common/k8s-api/endpoints/cron-job.api.ts b/src/common/k8s-api/endpoints/cron-job.api.ts index ad2db771d9..5c3dda4d7d 100644 --- a/src/common/k8s-api/endpoints/cron-job.api.ts +++ b/src/common/k8s-api/endpoints/cron-job.api.ts @@ -9,7 +9,6 @@ import { KubeObject } from "../kube-object"; import { formatDuration } from "../../utils/formatDuration"; import type { DerivedKubeApiOptions, IgnoredKubeApiOptions } from "../kube-api"; import { KubeApi } from "../kube-api"; -import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import type { JobTemplateSpec } from "./types/job-template-spec"; export class CronJobApi extends KubeApi { @@ -103,7 +102,3 @@ export class CronJob extends KubeObject { + assert(di.inject(createStoresAndApisInjectionToken), "jobApi is only available in certain environments"); + + return new JobApi(); + }, +}); + +export default jobApiInjectable; diff --git a/src/common/k8s-api/endpoints/job.api.ts b/src/common/k8s-api/endpoints/job.api.ts index 33b62790ea..252fc13f6e 100644 --- a/src/common/k8s-api/endpoints/job.api.ts +++ b/src/common/k8s-api/endpoints/job.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 { PodContainer, 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"; @@ -82,7 +81,7 @@ export class Job extends KubeObject status === "True"); } @@ -116,7 +115,3 @@ export function getMetricsForJobs(jobs: Job[], namespace: string, selector = "") namespace, }); } - -export const jobApi = isClusterPageContext() - ? new JobApi() - : undefined as never; diff --git a/src/common/k8s-api/endpoints/legacy-globals.ts b/src/common/k8s-api/endpoints/legacy-globals.ts index 4b48282771..ca0ad91225 100644 --- a/src/common/k8s-api/endpoints/legacy-globals.ts +++ b/src/common/k8s-api/endpoints/legacy-globals.ts @@ -6,8 +6,10 @@ import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; import clusterRoleBindingApiInjectable from "./cluster-role-binding.api.injectable"; import clusterRoleApiInjectable from "./cluster-role.api.injectable"; +import cronJobApiInjectable from "./cron-job.api.injectable"; import daemonSetApiInjectable from "./daemon-set.api.injectable"; import deploymentApiInjectable from "./deployment.api.injectable"; +import jobApiInjectable from "./job.api.injectable"; import podApiInjectable from "./pod.api.injectable"; import replicaSetApiInjectable from "./replica-set.api.injectable"; import roleApiInjectable from "./role.api.injectable"; @@ -58,3 +60,13 @@ export const statefulSetApi = asLegacyGlobalForExtensionApi(statefulSetApiInject * @deprecated use `di.inject(deploymentApiInjectable)` instead */ export const deploymentApi = asLegacyGlobalForExtensionApi(deploymentApiInjectable); + +/** + * @deprecated use `di.inject(cronJobApiInjectable)` instead + */ +export const cronJobApi = asLegacyGlobalForExtensionApi(cronJobApiInjectable); + +/** + * @deprecated use `di.inject(jobApiInjectable)` instead + */ +export const jobApi = asLegacyGlobalForExtensionApi(jobApiInjectable); diff --git a/src/extensions/main-api/k8s-api.ts b/src/extensions/main-api/k8s-api.ts index 74026ff68f..f13bdfe74b 100644 --- a/src/extensions/main-api/k8s-api.ts +++ b/src/extensions/main-api/k8s-api.ts @@ -5,7 +5,10 @@ import clusterRoleBindingApiInjectable from "../../common/k8s-api/endpoints/cluster-role-binding.api.injectable"; import clusterRoleApiInjectable from "../../common/k8s-api/endpoints/cluster-role.api.injectable"; +import cronJobApiInjectable from "../../common/k8s-api/endpoints/cron-job.api.injectable"; import daemonSetApiInjectable from "../../common/k8s-api/endpoints/daemon-set.api.injectable"; +import deploymentApiInjectable from "../../common/k8s-api/endpoints/deployment.api.injectable"; +import jobApiInjectable from "../../common/k8s-api/endpoints/job.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"; @@ -29,6 +32,9 @@ export const podsApi = asLegacyGlobalForExtensionApi(podApiInjectable); export const daemonSetApi = asLegacyGlobalForExtensionApi(daemonSetApiInjectable); export const replicaSetApi = asLegacyGlobalForExtensionApi(replicaSetApiInjectable); export const statefulSetApi = asLegacyGlobalForExtensionApi(statefulSetApiInjectable); +export const deploymentApi = asLegacyGlobalForExtensionApi(deploymentApiInjectable); +export const jobApi = asLegacyGlobalForExtensionApi(jobApiInjectable); +export const cronJobApi = asLegacyGlobalForExtensionApi(cronJobApiInjectable); export { ResourceStack } from "../../common/k8s/resource-stack"; export { apiManager } from "../../common/k8s-api/api-manager"; @@ -37,11 +43,11 @@ export { KubeObject, KubeStatus } from "../../common/k8s-api/kube-object"; export { KubeObjectStore } from "../../common/k8s-api/kube-object.store"; export { Pod, PodApi as PodsApi } from "../../common/k8s-api/endpoints/pod.api"; export { Node, nodeApi as nodesApi, NodeApi as NodesApi } from "../../common/k8s-api/endpoints/nodes.api"; -export { Deployment, deploymentApi, DeploymentApi } from "../../common/k8s-api/endpoints/deployment.api"; +export { Deployment, DeploymentApi } from "../../common/k8s-api/endpoints/deployment.api"; export { DaemonSet } from "../../common/k8s-api/endpoints/daemon-set.api"; export { StatefulSet } from "../../common/k8s-api/endpoints/stateful-set.api"; -export { Job, jobApi } from "../../common/k8s-api/endpoints/job.api"; -export { CronJob, cronJobApi } from "../../common/k8s-api/endpoints/cron-job.api"; +export { Job } from "../../common/k8s-api/endpoints/job.api"; +export { CronJob } 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 } from "../../common/k8s-api/endpoints/replica-set.api"; diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index c190863c3f..5857d6dc0e 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -16,6 +16,9 @@ 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"; import statefulSetApiInjectable from "../../common/k8s-api/endpoints/stateful-set.api.injectable"; +import deploymentApiInjectable from "../../common/k8s-api/endpoints/deployment.api.injectable"; +import jobApiInjectable from "../../common/k8s-api/endpoints/job.api.injectable"; +import cronJobApiInjectable from "../../common/k8s-api/endpoints/cron-job.api.injectable"; export function isAllowedResource(resource: KubeResource | KubeResource[]) { const resources = castArray(resource); @@ -38,6 +41,9 @@ export const podsApi = asLegacyGlobalForExtensionApi(podApiInjectable); export const daemonSetApi = asLegacyGlobalForExtensionApi(daemonSetApiInjectable); export const replicaSetApi = asLegacyGlobalForExtensionApi(replicaSetApiInjectable); export const statefulSetApi = asLegacyGlobalForExtensionApi(statefulSetApiInjectable); +export const deploymentApi = asLegacyGlobalForExtensionApi(deploymentApiInjectable); +export const jobApi = asLegacyGlobalForExtensionApi(jobApiInjectable); +export const cronJobApi = asLegacyGlobalForExtensionApi(cronJobApiInjectable); export { BaseKubeJsonApiObjectMetadata, @@ -49,11 +55,11 @@ export { KubeObject, KubeStatus } from "../../common/k8s-api/kube-object"; export { KubeObjectStore } from "../../common/k8s-api/kube-object.store"; export { Pod, PodApi as PodsApi } from "../../common/k8s-api/endpoints/pod.api"; export { Node, nodeApi as nodesApi, NodeApi as NodesApi } from "../../common/k8s-api/endpoints/nodes.api"; -export { Deployment, deploymentApi, DeploymentApi } from "../../common/k8s-api/endpoints/deployment.api"; +export { Deployment, DeploymentApi } from "../../common/k8s-api/endpoints/deployment.api"; export { DaemonSet } from "../../common/k8s-api/endpoints/daemon-set.api"; export { StatefulSet } from "../../common/k8s-api/endpoints/stateful-set.api"; -export { Job, jobApi } from "../../common/k8s-api/endpoints/job.api"; -export { CronJob, cronJobApi } from "../../common/k8s-api/endpoints/cron-job.api"; +export { Job } from "../../common/k8s-api/endpoints/job.api"; +export { CronJob } 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 } from "../../common/k8s-api/endpoints/replica-set.api"; @@ -93,8 +99,8 @@ export type { NodesStore } from "../../renderer/components/+nodes/nodes.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"; -export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/cronjob.store"; +export type { JobStore } from "../../renderer/components/+workloads-jobs/store"; +export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/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/store"; diff --git a/src/renderer/components/+workloads-cronjobs/cron-jobs-store.injectable.ts b/src/renderer/components/+workloads-cronjobs/cron-jobs-store.injectable.ts deleted file mode 100644 index a05ca0fc2a..0000000000 --- a/src/renderer/components/+workloads-cronjobs/cron-jobs-store.injectable.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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 { cronJobStore } from "./cronjob.store"; - -const cronJobsStoreInjectable = getInjectable({ - id: "cron-jobs-store", - instantiate: () => cronJobStore, - causesSideEffects: true, -}); - -export default cronJobsStoreInjectable; diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx index 550f235962..4b1d188d48 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx @@ -10,9 +10,9 @@ import kebabCase from "lodash/kebabCase"; import { disposeOnUnmount, observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge/badge"; -import { jobStore } from "../+workloads-jobs/job.store"; +import type { JobStore } from "../+workloads-jobs/store"; import { Link } from "react-router-dom"; -import { cronJobStore } from "./cronjob.store"; +import type { CronJobStore } from "./store"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { getDetailsUrl } from "../kube-detail-params"; import type { Job } from "../../../common/k8s-api/endpoints"; @@ -22,12 +22,16 @@ import logger from "../../../common/logger"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; +import cronJobStoreInjectable from "./store.injectable"; +import jobStoreInjectable from "../+workloads-jobs/store.injectable"; export interface CronJobDetailsProps extends KubeObjectDetailsProps { } interface Dependencies { subscribeStores: SubscribeStores; + jobStore: JobStore; + cronJobStore: CronJobStore; } @observer @@ -35,13 +39,13 @@ class NonInjectedCronJobDetails extends React.Component getProps: (di, props) => ({ ...props, subscribeStores: di.inject(subscribeStoresInjectable), + cronJobStore: di.inject(cronJobStoreInjectable), + jobStore: di.inject(jobStoreInjectable), }), }); diff --git a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx index 41812f3a9b..9d0da58f1b 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx @@ -7,8 +7,8 @@ import "./cronjobs.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cronJobStore } from "./cronjob.store"; -import { jobStore } from "../+workloads-jobs/job.store"; +import { cronJobStore } from "./legacy-store"; +import { jobStore } from "../+workloads-jobs/legacy-store"; import { eventStore } from "../+events/event.store"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/src/renderer/components/+workloads-cronjobs/legacy-store.ts b/src/renderer/components/+workloads-cronjobs/legacy-store.ts new file mode 100644 index 0000000000..880f8f5b0e --- /dev/null +++ b/src/renderer/components/+workloads-cronjobs/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 cronJobStoreInjectable from "./store.injectable"; + +/** + * @deprecated use `di.inject(cronJobStoreInjectable)` instead + */ +export const cronJobStore = asLegacyGlobalForExtensionApi(cronJobStoreInjectable); diff --git a/src/renderer/components/+workloads-cronjobs/store.injectable.ts b/src/renderer/components/+workloads-cronjobs/store.injectable.ts new file mode 100644 index 0000000000..c0f3ae0837 --- /dev/null +++ b/src/renderer/components/+workloads-cronjobs/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 getJobsByOwnerInjectable from "../+workloads-jobs/get-jobs-by-owner.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; +import cronJobApiInjectable from "../../../common/k8s-api/endpoints/cron-job.api.injectable"; +import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; +import { CronJobStore } from "./store"; + +const cronJobStoreInjectable = getInjectable({ + id: "cron-job-store", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectable), "cronJobStore is only available in certain environments"); + + const api = di.inject(cronJobApiInjectable); + const apiManager = di.inject(apiManagerInjectable); + const store = new CronJobStore({ + getJobsByOwner: di.inject(getJobsByOwnerInjectable), + }, api); + + apiManager.registerStore(store); + + return store; + }, +}); + +export default cronJobStoreInjectable; diff --git a/src/renderer/components/+workloads-cronjobs/cronjob.store.ts b/src/renderer/components/+workloads-cronjobs/store.ts similarity index 64% rename from src/renderer/components/+workloads-cronjobs/cronjob.store.ts rename to src/renderer/components/+workloads-cronjobs/store.ts index b2fa744a2b..67e006ac90 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob.store.ts +++ b/src/renderer/components/+workloads-cronjobs/store.ts @@ -3,14 +3,20 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; import type { CronJob, CronJobApi } from "../../../common/k8s-api/endpoints/cron-job.api"; -import { cronJobApi } from "../../../common/k8s-api/endpoints/cron-job.api"; -import { jobStore } from "../+workloads-jobs/job.store"; -import { apiManager } from "../../../common/k8s-api/api-manager"; -import { isClusterPageContext } from "../../utils"; +import type { GetJobsByOwner } from "../+workloads-jobs/get-jobs-by-owner.injectable"; + +interface Dependencies { + getJobsByOwner: GetJobsByOwner; +} export class CronJobStore extends KubeObjectStore { + constructor(protected readonly dependencies: Dependencies, api: CronJobApi, opts?: KubeObjectStoreOptions) { + super(api, opts); + } + getStatuses(cronJobs?: CronJob[]) { const status = { scheduled: 0, suspended: 0 }; @@ -28,18 +34,10 @@ export class CronJobStore extends KubeObjectStore { getActiveJobsNum(cronJob: CronJob) { // Active jobs are jobs without any condition 'Complete' nor 'Failed' - const jobs = jobStore.getJobsByOwner(cronJob); + const jobs = this.dependencies.getJobsByOwner(cronJob); if (!jobs.length) return 0; return jobs.filter(job => !job.getCondition()).length; } } - -export const cronJobStore = isClusterPageContext() - ? new CronJobStore(cronJobApi) - : undefined as never; - -if (isClusterPageContext()) { - apiManager.registerStore(cronJobStore); -} diff --git a/src/renderer/components/+workloads-jobs/get-jobs-by-owner.injectable.ts b/src/renderer/components/+workloads-jobs/get-jobs-by-owner.injectable.ts new file mode 100644 index 0000000000..3429ff5afb --- /dev/null +++ b/src/renderer/components/+workloads-jobs/get-jobs-by-owner.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { CronJob, Job } from "../../../common/k8s-api/endpoints"; +import { getInjectable } from "@ogre-tools/injectable"; +import jobStoreInjectable from "./store.injectable"; + +export type GetJobsByOwner = (cronJob: CronJob) => Job[]; + +const getJobsByOwnerInjectable = getInjectable({ + id: "get-jobs-by-owner", + instantiate: (di): GetJobsByOwner => { + const store = di.inject(jobStoreInjectable); + + return (cronJob) => store.getJobsByOwner(cronJob); + }, +}); + +export default getJobsByOwnerInjectable; diff --git a/src/renderer/components/+workloads-jobs/job-details.tsx b/src/renderer/components/+workloads-jobs/job-details.tsx index fd95c1a026..4988a917ba 100644 --- a/src/renderer/components/+workloads-jobs/job-details.tsx +++ b/src/renderer/components/+workloads-jobs/job-details.tsx @@ -14,7 +14,7 @@ import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses"; import { Link } from "react-router-dom"; import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations"; import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; -import { jobStore } from "./job.store"; +import type { JobStore } from "./store"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { getMetricsForJobs, type PodMetricData, Job } from "../../../common/k8s-api/endpoints"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; @@ -32,6 +32,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 jobStoreInjectable from "./store.injectable"; export interface JobDetailsProps extends KubeObjectDetailsProps { } @@ -39,6 +40,7 @@ export interface JobDetailsProps extends KubeObjectDetailsProps { interface Dependencies { subscribeStores: SubscribeStores; podStore: PodStore; + jobStore: JobStore; } @observer @@ -68,7 +70,7 @@ class NonInjectedJobDetails extends React.Component(NonInje ...props, subscribeStores: di.inject(subscribeStoresInjectable), podStore: di.inject(podStoreInjectable), + jobStore: di.inject(jobStoreInjectable), }), }); diff --git a/src/renderer/components/+workloads-jobs/jobs-store.injectable.ts b/src/renderer/components/+workloads-jobs/jobs-store.injectable.ts deleted file mode 100644 index 773706b8d6..0000000000 --- a/src/renderer/components/+workloads-jobs/jobs-store.injectable.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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 { jobStore } from "./job.store"; - -const jobsStoreInjectable = getInjectable({ - id: "jobs-store", - instantiate: () => jobStore, - causesSideEffects: true, -}); - -export default jobsStoreInjectable; diff --git a/src/renderer/components/+workloads-jobs/jobs.tsx b/src/renderer/components/+workloads-jobs/jobs.tsx index 61c629e519..49ca461bd9 100644 --- a/src/renderer/components/+workloads-jobs/jobs.tsx +++ b/src/renderer/components/+workloads-jobs/jobs.tsx @@ -7,7 +7,7 @@ import "./jobs.scss"; import React from "react"; import { observer } from "mobx-react"; -import { jobStore } from "./job.store"; +import { jobStore } from "./legacy-store"; import { eventStore } from "../+events/event.store"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import kebabCase from "lodash/kebabCase"; diff --git a/src/renderer/components/+workloads-jobs/legacy-store.ts b/src/renderer/components/+workloads-jobs/legacy-store.ts new file mode 100644 index 0000000000..b4b7e47f85 --- /dev/null +++ b/src/renderer/components/+workloads-jobs/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 jobStoreInjectable from "./store.injectable"; + +/** + * @deprecated use `di.inject(jobStoreInjectable)` instead + */ +export const jobStore = asLegacyGlobalForExtensionApi(jobStoreInjectable); diff --git a/src/renderer/components/+workloads-jobs/store.injectable.ts b/src/renderer/components/+workloads-jobs/store.injectable.ts new file mode 100644 index 0000000000..1dd9760dc5 --- /dev/null +++ b/src/renderer/components/+workloads-jobs/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 apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; +import jobApiInjectable from "../../../common/k8s-api/endpoints/job.api.injectable"; +import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; +import { JobStore } from "./store"; + +const jobStoreInjectable = getInjectable({ + id: "job-store", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectable), "jobStore is only available in certain environments"); + + const api = di.inject(jobApiInjectable); + const apiManager = di.inject(apiManagerInjectable); + const store = new JobStore({ + getPodsByOwnerId: di.inject(getPodsByOwnerIdInjectable), + }, api); + + apiManager.registerStore(store); + + return store; + }, +}); + +export default jobStoreInjectable; diff --git a/src/renderer/components/+workloads-jobs/job.store.ts b/src/renderer/components/+workloads-jobs/store.ts similarity index 74% rename from src/renderer/components/+workloads-jobs/job.store.ts rename to src/renderer/components/+workloads-jobs/store.ts index e14018be03..47fc09d931 100644 --- a/src/renderer/components/+workloads-jobs/job.store.ts +++ b/src/renderer/components/+workloads-jobs/store.ts @@ -3,18 +3,24 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; import type { Job, JobApi } from "../../../common/k8s-api/endpoints/job.api"; -import { jobApi } from "../../../common/k8s-api/endpoints/job.api"; import type { CronJob, Pod } from "../../../common/k8s-api/endpoints"; import { PodStatusPhase } from "../../../common/k8s-api/endpoints"; -import { podStore } from "../+workloads-pods/legacy-store"; -import { apiManager } from "../../../common/k8s-api/api-manager"; -import { isClusterPageContext } from "../../utils"; +import type { GetPodsByOwnerId } from "../+workloads-pods/get-pods-by-owner-id.injectable"; + +interface Dependencies { + getPodsByOwnerId: GetPodsByOwnerId; +} export class JobStore extends KubeObjectStore { + constructor(protected readonly dependencies: Dependencies, api: JobApi, opts?: KubeObjectStoreOptions) { + super(api, opts); + } + getChildPods(job: Job): Pod[] { - return podStore.getPodsByOwnerId(job.getId()); + return this.dependencies.getPodsByOwnerId(job.getId()); } getJobsByOwner(cronJob: CronJob) { @@ -44,11 +50,3 @@ export class JobStore extends KubeObjectStore { return status; } } - -export const jobStore = isClusterPageContext() - ? new JobStore(jobApi) - : undefined as never; - -if (isClusterPageContext()) { - apiManager.registerStore(jobStore); -} diff --git a/src/renderer/components/+workloads-overview/overview.tsx b/src/renderer/components/+workloads-overview/overview.tsx index fa028b962f..1157285e27 100644 --- a/src/renderer/components/+workloads-overview/overview.tsx +++ b/src/renderer/components/+workloads-overview/overview.tsx @@ -8,10 +8,10 @@ import "./overview.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { eventStore } from "../+events/event.store"; -import { deploymentStore } from "../+workloads-deployments/store"; +import type { 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"; +import type { JobStore } from "../+workloads-jobs/store"; +import type { CronJobStore } from "../+workloads-cronjobs/store"; import type { IComputedValue } from "mobx"; import { makeObservable, observable, reaction } from "mobx"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; @@ -30,6 +30,9 @@ import daemonSetStoreInjectable from "../+workloads-daemonsets/store.injectable" import podStoreInjectable from "../+workloads-pods/store.injectable"; import type { ReplicaSetStore } from "../+workloads-replicasets/store"; import replicaSetStoreInjectable from "../+workloads-replicasets/store.injectable"; +import cronJobStoreInjectable from "../+workloads-cronjobs/store.injectable"; +import deploymentStoreInjectable from "../+workloads-deployments/store.injectable"; +import jobStoreInjectable from "../+workloads-jobs/store.injectable"; interface Dependencies { detailComponents: IComputedValue[]>; @@ -38,6 +41,9 @@ interface Dependencies { podStore: PodStore; daemonSetStore: DaemonSetStore; replicaSetStore: ReplicaSetStore; + deploymentStore: DeploymentStore; + jobStore: JobStore; + cronJobStore: CronJobStore; } @observer @@ -52,11 +58,11 @@ class NonInjectedWorkloadsOverview extends React.Component { componentDidMount() { disposeOnUnmount(this, [ this.props.subscribeStores([ - cronJobStore, + this.props.cronJobStore, this.props.daemonSetStore, - deploymentStore, + this.props.deploymentStore, eventStore, - jobStore, + this.props.jobStore, this.props.podStore, this.props.replicaSetStore, statefulSetStore, @@ -118,5 +124,8 @@ export const WorkloadsOverview = withInjectables(NonInjectedWorklo daemonSetStore: di.inject(daemonSetStoreInjectable), podStore: di.inject(podStoreInjectable), replicaSetStore: di.inject(replicaSetStoreInjectable), + cronJobStore: di.inject(cronJobStoreInjectable), + deploymentStore: di.inject(deploymentStoreInjectable), + jobStore: di.inject(jobStoreInjectable), }), }); diff --git a/src/renderer/components/+workloads-overview/workloads/implementations/cron-jobs-workload.injectable.ts b/src/renderer/components/+workloads-overview/workloads/implementations/cron-jobs-workload.injectable.ts index 8171c17625..ac83557430 100644 --- a/src/renderer/components/+workloads-overview/workloads/implementations/cron-jobs-workload.injectable.ts +++ b/src/renderer/components/+workloads-overview/workloads/implementations/cron-jobs-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 cronJobsStoreInjectable from "../../../+workloads-cronjobs/cron-jobs-store.injectable"; +import cronJobsStoreInjectable from "../../../+workloads-cronjobs/store.injectable"; import { computed } from "mobx"; const cronJobsWorkloadInjectable = getInjectable({ diff --git a/src/renderer/components/+workloads-overview/workloads/implementations/jobs-workload.injectable.ts b/src/renderer/components/+workloads-overview/workloads/implementations/jobs-workload.injectable.ts index 19966b952b..43d6b5a0a2 100644 --- a/src/renderer/components/+workloads-overview/workloads/implementations/jobs-workload.injectable.ts +++ b/src/renderer/components/+workloads-overview/workloads/implementations/jobs-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 jobsStoreInjectable from "../../../+workloads-jobs/jobs-store.injectable"; +import jobStoreInjectable from "../../../+workloads-jobs/store.injectable"; import navigateToJobsInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/jobs/navigate-to-jobs.injectable"; import { computed } from "mobx"; @@ -16,7 +16,7 @@ const jobsWorkloadInjectable = getInjectable({ instantiate: (di) => { const navigate = di.inject(navigateToJobsInjectable); const namespaceStore = di.inject(namespaceStoreInjectable); - const store = di.inject(jobsStoreInjectable); + const store = di.inject(jobStoreInjectable); return { resourceName: "jobs", diff --git a/src/renderer/components/__tests__/cronjob.store.test.ts b/src/renderer/components/__tests__/cronjob.store.test.ts index 72566c799d..06cf25438e 100644 --- a/src/renderer/components/__tests__/cronjob.store.test.ts +++ b/src/renderer/components/__tests__/cronjob.store.test.ts @@ -2,33 +2,11 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { cronJobStore } from "../+workloads-cronjobs/cronjob.store"; -import type { CronJobSpec } from "../../../common/k8s-api/endpoints"; +import type { CronJobStore } from "../+workloads-cronjobs/store"; +import cronJobStoreInjectable from "../+workloads-cronjobs/store.injectable"; import { CronJob } from "../../../common/k8s-api/endpoints"; - -const spec: CronJobSpec = { - schedule: "test", - concurrencyPolicy: "test", - suspend: true, - jobTemplate: { - metadata: {}, - spec: { - template: { - metadata: {}, - spec: { - containers: [], - restartPolicy: "restart", - terminationGracePeriodSeconds: 1, - dnsPolicy: "no", - hostPID: true, - schedulerName: "string", - }, - }, - }, - }, - successfulJobsHistoryLimit: 1, - failedJobsHistoryLimit: 1, -}; +import createStoresAndApisInjectable from "../../create-stores-apis.injectable"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; const scheduledCronJob = new CronJob({ apiVersion: "foo", @@ -40,7 +18,29 @@ const scheduledCronJob = new CronJob({ namespace: "default", selfLink: "/apis/batch/v1beta1/cronjobs/default/scheduledCronJob", }, - spec, + spec: { + schedule: "test", + concurrencyPolicy: "test", + suspend: false, + jobTemplate: { + metadata: {}, + spec: { + template: { + metadata: {}, + spec: { + containers: [], + restartPolicy: "restart", + terminationGracePeriodSeconds: 1, + dnsPolicy: "no", + hostPID: true, + schedulerName: "string", + }, + }, + }, + }, + successfulJobsHistoryLimit: 1, + failedJobsHistoryLimit: 1, + }, }); const suspendedCronJob = new CronJob({ @@ -53,7 +53,29 @@ const suspendedCronJob = new CronJob({ namespace: "default", selfLink: "/apis/batch/v1beta1/cronjobs/default/suspendedCronJob", }, - spec, + spec: { + schedule: "test", + concurrencyPolicy: "test", + suspend: true, + jobTemplate: { + metadata: {}, + spec: { + template: { + metadata: {}, + spec: { + containers: [], + restartPolicy: "restart", + terminationGracePeriodSeconds: 1, + dnsPolicy: "no", + hostPID: true, + schedulerName: "string", + }, + }, + }, + }, + successfulJobsHistoryLimit: 1, + failedJobsHistoryLimit: 1, + }, }); const otherSuspendedCronJob = new CronJob({ @@ -66,12 +88,42 @@ const otherSuspendedCronJob = new CronJob({ namespace: "default", selfLink: "/apis/batch/v1beta1/cronjobs/default/otherSuspendedCronJob", }, - spec, + spec: { + schedule: "test", + concurrencyPolicy: "test", + suspend: true, + jobTemplate: { + metadata: {}, + spec: { + template: { + metadata: {}, + spec: { + containers: [], + restartPolicy: "restart", + terminationGracePeriodSeconds: 1, + dnsPolicy: "no", + hostPID: true, + schedulerName: "string", + }, + }, + }, + }, + successfulJobsHistoryLimit: 1, + failedJobsHistoryLimit: 1, + }, }); -scheduledCronJob.spec.suspend = false; - describe("CronJob Store tests", () => { + let cronJobStore: CronJobStore; + + beforeEach(() => { + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + di.override(createStoresAndApisInjectable, () => true); + + cronJobStore = di.inject(cronJobStoreInjectable); + }); + it("gets CronJob statuses in proper sorting order", () => { const statuses = Object.entries(cronJobStore.getStatuses([ suspendedCronJob, diff --git a/src/renderer/components/__tests__/job.store.test.ts b/src/renderer/components/__tests__/job.store.test.ts index 4423863d91..ed4580a660 100644 --- a/src/renderer/components/__tests__/job.store.test.ts +++ b/src/renderer/components/__tests__/job.store.test.ts @@ -4,7 +4,7 @@ */ import { observable } from "mobx"; -import { jobStore } from "../+workloads-jobs/job.store"; +import { jobStore } from "../+workloads-jobs/store"; import { podStore } from "../+workloads-pods/legacy-store"; import { Job, Pod } from "../../../common/k8s-api/endpoints";