diff --git a/src/common/k8s-api/endpoints/legacy-globals.ts b/src/common/k8s-api/endpoints/legacy-globals.ts index 6af7bc1e77..2a30383932 100644 --- a/src/common/k8s-api/endpoints/legacy-globals.ts +++ b/src/common/k8s-api/endpoints/legacy-globals.ts @@ -6,6 +6,7 @@ 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 roleApiInjectable from "./role.api.injectable"; import serviceAccountApiInjectable from "./service-account.api.injectable"; /** @@ -22,3 +23,8 @@ export const clusterRoleApi = asLegacyGlobalForExtensionApi(clusterRoleApiInject * @deprecated use `di.inject(serviceAccountApiInjectable)` instead */ export const serviceAccountApi = asLegacyGlobalForExtensionApi(serviceAccountApiInjectable); + +/** + * @deprecated use `di.inject(roleApiInjectable)` instead + */ +export const roleApi = asLegacyGlobalForExtensionApi(roleApiInjectable); diff --git a/src/common/k8s-api/endpoints/namespaces.api.ts b/src/common/k8s-api/endpoints/namespaces.api.ts index 3c33394c13..cbfe366d05 100644 --- a/src/common/k8s-api/endpoints/namespaces.api.ts +++ b/src/common/k8s-api/endpoints/namespaces.api.ts @@ -3,6 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { DerivedKubeApiOptions, IgnoredKubeApiOptions } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { KubeObjectScope, KubeObjectStatus } from "../kube-object"; import { KubeObject } from "../kube-object"; @@ -34,6 +35,12 @@ export class Namespace extends KubeObject { + constructor(opts: DerivedKubeApiOptions & IgnoredKubeApiOptions = {}) { + super({ + ...opts, + objectConstructor: Namespace, + }); + } } export function getMetricsForNamespace(namespace: string, selector = ""): Promise { @@ -52,14 +59,6 @@ export function getMetricsForNamespace(namespace: string, selector = ""): Promis }); } -let namespacesApi: NamespaceApi; - -if (isClusterPageContext()) { - namespacesApi = new NamespaceApi({ - objectConstructor: Namespace, - }); -} - -export { - namespacesApi, -}; +export const namespaceApi = isClusterPageContext() + ? new NamespaceApi() + : undefined as never; diff --git a/src/common/k8s-api/endpoints/role.api.injectable.ts b/src/common/k8s-api/endpoints/role.api.injectable.ts new file mode 100644 index 0000000000..09ef7ba629 --- /dev/null +++ b/src/common/k8s-api/endpoints/role.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 { RoleApi } from "./role.api"; + +const roleApiInjectable = getInjectable({ + id: "role-api", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectionToken), "roleApi is only available in certain environments"); + + return new RoleApi(); + }, +}); + +export default roleApiInjectable; diff --git a/src/common/k8s-api/endpoints/role.api.ts b/src/common/k8s-api/endpoints/role.api.ts index 0d17a152b6..a98c580088 100644 --- a/src/common/k8s-api/endpoints/role.api.ts +++ b/src/common/k8s-api/endpoints/role.api.ts @@ -7,7 +7,6 @@ import type { KubeObjectMetadata, KubeObjectScope } from "../kube-object"; import { KubeObject } from "../kube-object"; import type { DerivedKubeApiOptions } from "../kube-api"; import { KubeApi } from "../kube-api"; -import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import type { KubeJsonApiData } from "../kube-json-api"; import type { PolicyRule } from "./types/policy-rule"; @@ -39,7 +38,3 @@ export class RoleApi extends KubeApi { }); } } - -export const roleApi = isClusterPageContext() - ? new RoleApi() - : undefined as never; diff --git a/src/extensions/main-api/k8s-api.ts b/src/extensions/main-api/k8s-api.ts index 80014f61f1..7203b86708 100644 --- a/src/extensions/main-api/k8s-api.ts +++ b/src/extensions/main-api/k8s-api.ts @@ -5,6 +5,7 @@ import clusterRoleBindingApiInjectable from "../../common/k8s-api/endpoints/cluster-role-binding.api.injectable"; import clusterRoleApiInjectable from "../../common/k8s-api/endpoints/cluster-role.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"; @@ -19,6 +20,7 @@ export function isAllowedResource(...args: any[]) { export const serviceAccountsApi = asLegacyGlobalForExtensionApi(serviceAccountApiInjectable); export const clusterRoleApi = asLegacyGlobalForExtensionApi(clusterRoleApiInjectable); export const clusterRoleBindingApi = asLegacyGlobalForExtensionApi(clusterRoleBindingApiInjectable); +export const roleApi = asLegacyGlobalForExtensionApi(roleApiInjectable); export { ResourceStack } from "../../common/k8s/resource-stack"; export { apiManager } from "../../common/k8s-api/api-manager"; @@ -46,10 +48,10 @@ export { NetworkPolicy, networkPolicyApi } from "../../common/k8s-api/endpoints/ export { PersistentVolume, persistentVolumeApi } from "../../common/k8s-api/endpoints/persistent-volume.api"; export { PersistentVolumeClaim, persistentVolumeClaimApi as pvcApi, PersistentVolumeClaimApi as PersistentVolumeClaimsApi } from "../../common/k8s-api/endpoints/persistent-volume-claims.api"; export { StorageClass, storageClassApi } from "../../common/k8s-api/endpoints/storage-class.api"; -export { Namespace, namespacesApi } from "../../common/k8s-api/endpoints/namespaces.api"; +export { Namespace, namespaceApi as namespacesApi } from "../../common/k8s-api/endpoints/namespaces.api"; export { KubeEvent, eventApi } from "../../common/k8s-api/endpoints/events.api"; export { ServiceAccount } from "../../common/k8s-api/endpoints/service-account.api"; -export { Role, roleApi } from "../../common/k8s-api/endpoints/role.api"; +export { Role } from "../../common/k8s-api/endpoints/role.api"; export { RoleBinding, roleBindingApi } from "../../common/k8s-api/endpoints/role-binding.api"; export { ClusterRole } from "../../common/k8s-api/endpoints/cluster-role.api"; export { ClusterRoleBinding } from "../../common/k8s-api/endpoints/cluster-role-binding.api"; diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index 5ec3328131..c9d9de6629 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -11,6 +11,7 @@ import clusterRoleBindingApiInjectable from "../../common/k8s-api/endpoints/clus import clusterRoleApiInjectable from "../../common/k8s-api/endpoints/cluster-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"; +import roleApiInjectable from "../../common/k8s-api/endpoints/role.api.injectable"; export function isAllowedResource(resource: KubeResource | KubeResource[]) { const resources = castArray(resource); @@ -28,6 +29,7 @@ export function isAllowedResource(resource: KubeResource | KubeResource[]) { export const serviceAccountsApi = asLegacyGlobalForExtensionApi(serviceAccountApiInjectable); export const clusterRoleApi = asLegacyGlobalForExtensionApi(clusterRoleApiInjectable); export const clusterRoleBindingApi = asLegacyGlobalForExtensionApi(clusterRoleBindingApiInjectable); +export const roleApi = asLegacyGlobalForExtensionApi(roleApiInjectable); export { BaseKubeJsonApiObjectMetadata, @@ -58,10 +60,10 @@ export { NetworkPolicy, networkPolicyApi } from "../../common/k8s-api/endpoints" export { PersistentVolume, persistentVolumeApi } from "../../common/k8s-api/endpoints"; export { PersistentVolumeClaim, persistentVolumeClaimApi as pvcApi, PersistentVolumeClaimApi as PersistentVolumeClaimsApi } from "../../common/k8s-api/endpoints"; export { StorageClass, storageClassApi } from "../../common/k8s-api/endpoints"; -export { Namespace, namespacesApi } from "../../common/k8s-api/endpoints"; +export { Namespace, namespaceApi as namespacesApi } from "../../common/k8s-api/endpoints"; export { KubeEvent, eventApi } from "../../common/k8s-api/endpoints"; export { ServiceAccount } from "../../common/k8s-api/endpoints"; -export { Role, roleApi } from "../../common/k8s-api/endpoints"; +export { Role } from "../../common/k8s-api/endpoints"; export { RoleBinding, roleBindingApi } from "../../common/k8s-api/endpoints"; export { ClusterRole } from "../../common/k8s-api/endpoints"; export { ClusterRoleBinding } from "../../common/k8s-api/endpoints"; @@ -102,7 +104,7 @@ export type { PersistentVolumeClaimStore as VolumeClaimStore } from "../../rende export type { StorageClassStore } from "../../renderer/components/+storage-classes/storage-class.store"; export type { NamespaceStore } from "../../renderer/components/+namespaces/namespace-store/namespace.store"; export type { ServiceAccountStore as ServiceAccountsStore } from "../../renderer/components/+user-management/+service-accounts/store"; -export type { RolesStore } from "../../renderer/components/+user-management/+roles/store"; +export type { RoleStore as RolesStore } from "../../renderer/components/+user-management/+roles/store"; export type { RoleBindingStore as RoleBindingsStore } from "../../renderer/components/+user-management/+role-bindings/store"; export type { CRDStore } from "../../renderer/components/+custom-resources/crd.store"; export type { CRDResourceStore } from "../../renderer/components/+custom-resources/crd-resource.store"; diff --git a/src/renderer/components/+namespaces/namespace-store/namespace-store.injectable.ts b/src/renderer/components/+namespaces/namespace-store/namespace-store.injectable.ts index 636bb58993..9819e0bc73 100644 --- a/src/renderer/components/+namespaces/namespace-store/namespace-store.injectable.ts +++ b/src/renderer/components/+namespaces/namespace-store/namespace-store.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { NamespaceStore } from "./namespace.store"; import apiManagerInjectable from "../../kube-object-menu/dependencies/api-manager.injectable"; import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable"; -import { namespacesApi } from "../../../../common/k8s-api/endpoints"; +import { namespaceApi } from "../../../../common/k8s-api/endpoints"; const namespaceStoreInjectable = getInjectable({ id: "namespace-store", @@ -21,7 +21,7 @@ const namespaceStoreInjectable = getInjectable({ const namespaceStore = new NamespaceStore({ storage, - }, namespacesApi); + }, namespaceApi); const apiManager = di.inject(apiManagerInjectable); diff --git a/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx b/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx index c1bbc12c9e..30047c11f6 100644 --- a/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx +++ b/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx @@ -21,7 +21,7 @@ import { Notifications } from "../../notifications"; import { Select } from "../../select"; import { Wizard, WizardStep } from "../../wizard"; import { clusterRoleBindingStore } from "./legacy-store"; -import { clusterRolesStore } from "../+cluster-roles/legacy-store"; +import { clusterRoleStore } from "../+cluster-roles/legacy-store"; import { ObservableHashSet, nFircate } from "../../../utils"; import { Input } from "../../input"; import { TooltipPosition } from "../../tooltip"; @@ -106,7 +106,7 @@ export class ClusterRoleBindingDialog extends React.Component item.getName() === binding.roleRef.name); this.bindingName = binding.getName(); @@ -164,7 +164,7 @@ export class ClusterRoleBindingDialog extends React.Component ( diff --git a/src/renderer/components/+user-management/+cluster-roles/add-dialog.tsx b/src/renderer/components/+user-management/+cluster-roles/add-dialog.tsx index e296949af4..01c6cc4831 100644 --- a/src/renderer/components/+user-management/+cluster-roles/add-dialog.tsx +++ b/src/renderer/components/+user-management/+cluster-roles/add-dialog.tsx @@ -15,7 +15,7 @@ import { showDetails } from "../../kube-detail-params"; import { SubTitle } from "../../layout/sub-title"; import { Notifications } from "../../notifications"; import { Wizard, WizardStep } from "../../wizard"; -import { clusterRolesStore } from "./legacy-store"; +import { clusterRoleStore } from "./legacy-store"; export interface AddClusterRoleDialogProps extends Partial { } @@ -45,7 +45,7 @@ export class AddClusterRoleDialog extends React.Component { try { - const role = await clusterRolesStore.create({ name: this.clusterRoleName }); + const role = await clusterRoleStore.create({ name: this.clusterRoleName }); showDetails(role.selfLink); this.reset(); diff --git a/src/renderer/components/+user-management/+cluster-roles/legacy-store.ts b/src/renderer/components/+user-management/+cluster-roles/legacy-store.ts index adf5d5176e..79a9811591 100644 --- a/src/renderer/components/+user-management/+cluster-roles/legacy-store.ts +++ b/src/renderer/components/+user-management/+cluster-roles/legacy-store.ts @@ -9,4 +9,4 @@ import clusterRoleStoreInjectable from "./store.injectable"; /** * @deprecated use `di.inject(clusterRoleStoreInjectable)` instead */ -export const clusterRolesStore = asLegacyGlobalForExtensionApi(clusterRoleStoreInjectable); +export const clusterRoleStore = asLegacyGlobalForExtensionApi(clusterRoleStoreInjectable); diff --git a/src/renderer/components/+user-management/+cluster-roles/view.tsx b/src/renderer/components/+user-management/+cluster-roles/view.tsx index d55a843b84..86334aebe3 100644 --- a/src/renderer/components/+user-management/+cluster-roles/view.tsx +++ b/src/renderer/components/+user-management/+cluster-roles/view.tsx @@ -10,7 +10,7 @@ import React from "react"; import { KubeObjectListLayout } from "../../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../../kube-object-status-icon"; import { AddClusterRoleDialog } from "./add-dialog"; -import { clusterRolesStore } from "./legacy-store"; +import { clusterRoleStore } from "./legacy-store"; import { SiblingsInTabLayout } from "../../layout/siblings-in-tab-layout"; import { KubeObjectAge } from "../../kube-object/age"; @@ -29,7 +29,7 @@ export class ClusterRoles extends React.Component { isConfigurable tableId="access_cluster_roles" className="ClusterRoles" - store={clusterRolesStore} + store={clusterRoleStore} sortingCallbacks={{ [columnId.name]: clusterRole => clusterRole.getName(), [columnId.age]: clusterRole => -clusterRole.getCreationTimestamp(), diff --git a/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx b/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx index af1bb862e3..101204846b 100644 --- a/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx +++ b/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx @@ -5,16 +5,14 @@ import userEvent from "@testing-library/user-event"; import React from "react"; -import { clusterRolesStore } from "../../+cluster-roles/store"; import { ClusterRole } from "../../../../../common/k8s-api/endpoints"; import { RoleBindingDialog } from "../dialog"; import { getDiForUnitTesting } from "../../../../getDiForUnitTesting"; import type { DiRender } from "../../../test-utils/renderFor"; import { renderFor } from "../../../test-utils/renderFor"; -import directoryForUserDataInjectable - from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; - -jest.mock("../../+cluster-roles/store"); +import directoryForUserDataInjectable from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import clusterRoleStoreInjectable from "../../+cluster-roles/store.injectable"; +import createStoresAndApisInjectable from "../../../../create-stores-apis.injectable"; describe("RoleBindingDialog tests", () => { let render: DiRender; @@ -22,13 +20,16 @@ describe("RoleBindingDialog tests", () => { beforeEach(async () => { const di = getDiForUnitTesting({ doGeneralOverrides: true }); + di.override(createStoresAndApisInjectable, () => true); di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); await di.runSetups(); render = renderFor(di); - clusterRolesStore.items.replace([ + const store = di.inject(clusterRoleStoreInjectable); + + store.items.replace([ new ClusterRole({ apiVersion: "rbac.authorization.k8s.io/v1", kind: "ClusterRole", diff --git a/src/renderer/components/+user-management/+role-bindings/dialog.tsx b/src/renderer/components/+user-management/+role-bindings/dialog.tsx index 474c20dd34..17f4153f44 100644 --- a/src/renderer/components/+user-management/+role-bindings/dialog.tsx +++ b/src/renderer/components/+user-management/+role-bindings/dialog.tsx @@ -9,8 +9,8 @@ import { computed, observable, makeObservable, action } from "mobx"; import { observer } from "mobx-react"; import React from "react"; -import { rolesStore } from "../+roles/store"; -import { serviceAccountsStore } from "../+service-accounts/store"; +import { roleStore } from "../+roles/legacy-store"; +import { serviceAccountStore } from "../+service-accounts/legacy-store"; import { NamespaceSelect } from "../../+namespaces/namespace-select"; import type { ClusterRole, Role, RoleBinding, ServiceAccount } from "../../../../common/k8s-api/endpoints"; import { roleApi } from "../../../../common/k8s-api/endpoints"; @@ -24,7 +24,7 @@ import { Notifications } from "../../notifications"; import { Select } from "../../select"; import { Wizard, WizardStep } from "../../wizard"; import { roleBindingStore } from "./store"; -import { clusterRolesStore } from "../+cluster-roles/store"; +import { clusterRoleStore } from "../+cluster-roles/legacy-store"; import { Input } from "../../input"; import { ObservableHashSet, nFircate } from "../../../utils"; import type { Subject } from "../../../../common/k8s-api/endpoints/types/subject"; @@ -96,9 +96,9 @@ export class RoleBindingDialog extends React.Component { } @computed get roleRefOptions(): (Role | ClusterRole)[] { - const roles = rolesStore.items + const roles = roleStore.items .filter(role => role.getNs() === this.bindingNamespace); - const clusterRoles = clusterRolesStore.items; + const clusterRoles = clusterRoleStore.items; return [ ...roles, @@ -117,8 +117,8 @@ export class RoleBindingDialog extends React.Component { this.selectedRoleRef = ( binding.roleRef.kind === roleApi.kind - ? rolesStore.items.find(findByRoleRefName) - : clusterRolesStore.items.find(findByRoleRefName) + ? roleStore.items.find(findByRoleRefName) + : clusterRoleStore.items.find(findByRoleRefName) ); this.bindingName = binding.getName(); @@ -128,7 +128,7 @@ export class RoleBindingDialog extends React.Component { const accountNames = new Set(saSubjects.map(acc => acc.name)); this.selectedAccounts.replace( - serviceAccountsStore.items + serviceAccountStore.items .filter(sa => accountNames.has(sa.getName())), ); this.selectedUsers.replace(uSubjects.map(user => user.name)); @@ -234,7 +234,7 @@ export class RoleBindingDialog extends React.Component { isMulti themeName="light" placeholder="Select service accounts ..." - options={serviceAccountsStore.items} + options={serviceAccountStore.items} isOptionSelected={account => this.selectedAccounts.has(account)} formatOptionLabel={account => ( <> diff --git a/src/renderer/components/+user-management/+roles/legacy-store.ts b/src/renderer/components/+user-management/+roles/legacy-store.ts new file mode 100644 index 0000000000..84ecdaa588 --- /dev/null +++ b/src/renderer/components/+user-management/+roles/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 roleStoreInjectable from "./store.injectable"; + +/** + * @deprecated use `di.inject(roleStoreInjectable)` instead + */ +export const roleStore = asLegacyGlobalForExtensionApi(roleStoreInjectable); diff --git a/src/renderer/components/+user-management/+roles/store.injectable.ts b/src/renderer/components/+user-management/+roles/store.injectable.ts new file mode 100644 index 0000000000..803edc00a2 --- /dev/null +++ b/src/renderer/components/+user-management/+roles/store.injectable.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import 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 { RoleStore } from "./store"; + +const roleStoreInjectable = getInjectable({ + id: "role-store", + instantiate: (di) => { + assert(di.inject(createStoresAndApisInjectable), "roleStore is only available in certain environments"); + + const api = di.inject(roleApiInjectable); + const apiManager = di.inject(apiManagerInjectable); + const store = new RoleStore(api); + + apiManager.registerStore(store); + + return store; + }, +}); + +export default roleStoreInjectable; diff --git a/src/renderer/components/+user-management/+roles/store.ts b/src/renderer/components/+user-management/+roles/store.ts index 11d393d338..5292d9b699 100644 --- a/src/renderer/components/+user-management/+roles/store.ts +++ b/src/renderer/components/+user-management/+roles/store.ts @@ -2,13 +2,10 @@ * 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 type { Role, RoleApi, RoleData } from "../../../../common/k8s-api/endpoints"; -import { roleApi } from "../../../../common/k8s-api/endpoints"; import { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; -import { isClusterPageContext } from "../../../utils"; -export class RolesStore extends KubeObjectStore { +export class RoleStore extends KubeObjectStore { protected sortItems(items: Role[]) { return super.sortItems(items, [ role => role.kind, @@ -16,11 +13,3 @@ export class RolesStore extends KubeObjectStore { ]); } } - -export const rolesStore = isClusterPageContext() - ? new RolesStore(roleApi) - : undefined as never; - -if (isClusterPageContext()) { - apiManager.registerStore(rolesStore); -}