1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Remove usages of legacy global roleApi

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-12-22 11:16:20 -05:00
parent 4fdc92a039
commit b098df62e1
11 changed files with 165 additions and 79 deletions

View File

@ -43,5 +43,4 @@ export * from "./service.api";
export * from "./service-account.api";
export * from "./stateful-set.api";
export * from "./storage-class.api";
export * from "./legacy-globals";
export * from "./types";

View File

@ -1,12 +0,0 @@
/**
* 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 roleApiInjectable from "./role.api.injectable";
/**
* @deprecated use `di.inject(roleApiInjectable)` instead
*/
export const roleApi = asLegacyGlobalForExtensionApi(roleApiInjectable);

View File

@ -6,7 +6,7 @@
import userEvent from "@testing-library/user-event";
import React from "react";
import { ClusterRole } from "../../../../../common/k8s-api/endpoints";
import { RoleBindingDialog } from "../dialog";
import { RoleBindingDialog } from "../dialog/view";
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
import type { DiRender } from "../../../test-utils/renderFor";
import { renderFor } from "../../../test-utils/renderFor";
@ -16,9 +16,12 @@ import storesAndApisCanBeCreatedInjectable from "../../../../stores-apis-can-be-
import directoryForKubeConfigsInjectable from "../../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
import hostedClusterInjectable from "../../../../cluster-frame-context/hosted-cluster.injectable";
import createClusterInjectable from "../../../../cluster/create-cluster.injectable";
import type { OpenRoleBindingDialog } from "../dialog/open.injectable";
import openRoleBindingDialogInjectable from "../dialog/open.injectable";
describe("RoleBindingDialog tests", () => {
let render: DiRender;
let openRoleBindingDialog: OpenRoleBindingDialog;
beforeEach(() => {
const di = getDiForUnitTesting({ doGeneralOverrides: true });
@ -27,6 +30,8 @@ describe("RoleBindingDialog tests", () => {
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
di.override(storesAndApisCanBeCreatedInjectable, () => true);
openRoleBindingDialog = di.inject(openRoleBindingDialogInjectable);
const createCluster = di.inject(createClusterInjectable);
di.override(hostedClusterInjectable, () => createCluster({
@ -55,11 +60,6 @@ describe("RoleBindingDialog tests", () => {
]);
});
afterEach(() => {
RoleBindingDialog.close();
jest.resetAllMocks();
});
it("should render without any errors", () => {
const { container } = render(<RoleBindingDialog />);
@ -67,7 +67,7 @@ describe("RoleBindingDialog tests", () => {
});
it("role select should be searchable", async () => {
RoleBindingDialog.open();
openRoleBindingDialog();
const res = render(<RoleBindingDialog />);
userEvent.click(await res.findByText("Select role", { exact: false }));

View File

@ -14,19 +14,21 @@ import { AddRemoveButtons } from "../../add-remove-buttons";
import { DrawerTitle } from "../../drawer";
import type { KubeObjectDetailsProps } from "../../kube-object-details";
import { Table, TableCell, TableHead, TableRow } from "../../table";
import { RoleBindingDialog } from "./dialog";
import { roleBindingStore } from "./legacy-store";
import { ObservableHashSet } from "../../../../common/utils/hash-set";
import { hashSubject } from "../hashers";
import type { OpenConfirmDialog } from "../../confirm-dialog/open.injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import openConfirmDialogInjectable from "../../confirm-dialog/open.injectable";
import type { OpenRoleBindingDialog } from "./dialog/open.injectable";
import openRoleBindingDialogInjectable from "./dialog/open.injectable";
export interface RoleBindingDetailsProps extends KubeObjectDetailsProps<RoleBinding> {
}
interface Dependencies {
openConfirmDialog: OpenConfirmDialog;
openRoleBindingDialog: OpenRoleBindingDialog;
}
@observer
@ -60,7 +62,7 @@ class NonInjectedRoleBindingDetails extends React.Component<RoleBindingDetailsPr
render() {
const { selectedSubjects } = this;
const { object: roleBinding } = this.props;
const { object: roleBinding, openRoleBindingDialog } = this.props;
if (!roleBinding) {
return null;
@ -116,7 +118,7 @@ class NonInjectedRoleBindingDetails extends React.Component<RoleBindingDetailsPr
)}
<AddRemoveButtons
onAdd={() => RoleBindingDialog.open(roleBinding)}
onAdd={() => openRoleBindingDialog(roleBinding)}
onRemove={selectedSubjects.size ? this.removeSelectedSubjects : undefined}
addTooltip={`Edit bindings of ${roleRef.name}`}
removeTooltip={`Remove selected bindings from ${roleRef.name}`}
@ -130,5 +132,6 @@ export const RoleBindingDetails = withInjectables<Dependencies, RoleBindingDetai
getProps: (di, props) => ({
...props,
openConfirmDialog: di.inject(openConfirmDialogInjectable),
openRoleBindingDialog: di.inject(openRoleBindingDialogInjectable),
}),
});

View File

@ -0,0 +1,18 @@
/**
* 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 { action } from "mobx";
import roleBindingDialogStateInjectable from "./state.injectable";
const closeRoleBindingDialogInjectable = getInjectable({
id: "close-role-binding-dialog",
instantiate: (di) => {
const state = di.inject(roleBindingDialogStateInjectable);
return action(() => state.set({ isOpen: false }));
},
});
export default closeRoleBindingDialogInjectable;

View File

@ -0,0 +1,24 @@
/**
* 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 { action } from "mobx";
import type { RoleBinding } from "../../../../../common/k8s-api/endpoints";
import roleBindingDialogStateInjectable from "./state.injectable";
export type OpenRoleBindingDialog = (roleBinding?: RoleBinding | undefined) => void;
const openRoleBindingDialogInjectable = getInjectable({
id: "open-role-binding-dialog",
instantiate: (di): OpenRoleBindingDialog => {
const state = di.inject(roleBindingDialogStateInjectable);
return action((roleBinding) => state.set({
isOpen: true,
roleBinding,
}));
},
});
export default openRoleBindingDialogInjectable;

View File

@ -0,0 +1,22 @@
/**
* 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 { observable } from "mobx";
import type { RoleBinding } from "../../../../../common/k8s-api/endpoints";
export type RoleBindingDialogState = {
isOpen: false;
roleBinding?: undefined;
} | {
isOpen: true;
roleBinding: RoleBinding | undefined;
};
const roleBindingDialogStateInjectable = getInjectable({
id: "role-binding-dialog-state",
instantiate: () => observable.box<RoleBindingDialogState>({ isOpen: false }),
});
export default roleBindingDialogStateInjectable;

View File

@ -3,64 +3,65 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import "./dialog.scss";
import "./view.scss";
import type { IObservableValue } from "mobx";
import { computed, observable, makeObservable, action } from "mobx";
import { observer } from "mobx-react";
import React from "react";
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";
import type { DialogProps } from "../../dialog";
import { Dialog } from "../../dialog";
import { EditableList } from "../../editable-list";
import { Icon } from "../../icon";
import { showDetails } from "../../kube-detail-params";
import { SubTitle } from "../../layout/sub-title";
import { Notifications } from "../../notifications";
import type { SelectOption } from "../../select";
import { onMultiSelectFor, Select } from "../../select";
import { Wizard, WizardStep } from "../../wizard";
import { roleBindingStore } from "./legacy-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";
import { NamespaceSelect } from "../../../+namespaces/namespace-select";
import type { ClusterRole, Role, RoleApi, ServiceAccount } from "../../../../../common/k8s-api/endpoints";
import type { DialogProps } from "../../../dialog";
import { Dialog } from "../../../dialog";
import { EditableList } from "../../../editable-list";
import { Icon } from "../../../icon";
import { SubTitle } from "../../../layout/sub-title";
import { Notifications } from "../../../notifications";
import type { SelectOption } from "../../../select";
import { onMultiSelectFor, Select } from "../../../select";
import { Wizard, WizardStep } from "../../../wizard";
import { Input } from "../../../input";
import { ObservableHashSet, nFircate } from "../../../../utils";
import type { Subject } from "../../../../../common/k8s-api/endpoints/types/subject";
import type { RoleBindingDialogState } from "./state.injectable";
import type { RoleBindingStore } from "../store";
import { withInjectables } from "@ogre-tools/injectable-react";
import roleBindingStoreInjectable from "../store.injectable";
import roleBindingDialogStateInjectable from "./state.injectable";
import closeRoleBindingDialogInjectable from "./close.injectable";
import type { ShowDetails } from "../../../kube-detail-params/show-details.injectable";
import type { RoleStore } from "../../+roles/store";
import type { ClusterRoleStore } from "../../+cluster-roles/store";
import type { ServiceAccountStore } from "../../+service-accounts/store";
import showDetailsInjectable from "../../../kube-detail-params/show-details.injectable";
import clusterRoleStoreInjectable from "../../+cluster-roles/store.injectable";
import roleStoreInjectable from "../../+roles/store.injectable";
import serviceAccountStoreInjectable from "../../+service-accounts/store.injectable";
import roleApiInjectable from "../../../../../common/k8s-api/endpoints/role.api.injectable";
export interface RoleBindingDialogProps extends Partial<DialogProps> {
}
interface DialogState {
isOpen: boolean;
data?: RoleBinding;
interface Dependencies {
state: IObservableValue<RoleBindingDialogState>;
roleBindingStore: RoleBindingStore;
closeRoleBindingDialog: () => void;
showDetails: ShowDetails;
roleStore: RoleStore;
clusterRoleStore: ClusterRoleStore;
serviceAccountStore: ServiceAccountStore;
roleApi: RoleApi;
}
@observer
export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
static state = observable.object<DialogState>({
isOpen: false,
});
constructor(props: RoleBindingDialogProps) {
class NonInjectedRoleBindingDialog extends React.Component<RoleBindingDialogProps & Dependencies> {
constructor(props: RoleBindingDialogProps & Dependencies) {
super(props);
makeObservable(this);
}
static open(roleBinding?: RoleBinding) {
RoleBindingDialog.state.isOpen = true;
RoleBindingDialog.state.data = roleBinding;
}
static close() {
RoleBindingDialog.state.isOpen = false;
RoleBindingDialog.state.data = undefined;
}
get roleBinding() {
return RoleBindingDialog.state.data;
@computed get roleBinding() {
return this.props.state.get().roleBinding;
}
@computed get isEditing() {
@ -97,6 +98,10 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
}
@computed get roleRefOptions(): SelectOption<Role | ClusterRole>[] {
const {
roleStore,
clusterRoleStore,
} = this.props;
const roles = roleStore.items
.filter(role => role.getNs() === this.bindingNamespace);
const clusterRoles = clusterRoleStore.items;
@ -111,7 +116,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
}
@computed get serviceAccountOptions(): SelectOption<ServiceAccount>[] {
return serviceAccountStore.items.map(serviceAccount => ({
return this.props.serviceAccountStore.items.map(serviceAccount => ({
value: serviceAccount,
label: `${serviceAccount.getName()} (${serviceAccount.getNs()})`,
isSelected: this.selectedAccounts.has(serviceAccount),
@ -119,18 +124,22 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
}
onOpen = action(() => {
const {
roleStore,
clusterRoleStore,
serviceAccountStore,
roleApi,
} = this.props;
const binding = this.roleBinding;
if (!binding) {
return this.reset();
}
const findByRoleRefName = (item: Role | ClusterRole) => item.getName() === binding.roleRef.name;
this.selectedRoleRef = (
binding.roleRef.kind === roleApi.kind
? roleStore.items.find(findByRoleRefName)
: clusterRoleStore.items.find(findByRoleRefName)
? roleStore.items.find(item => item.getName() === binding.roleRef.name)
: clusterRoleStore.items.find(item => item.getName() === binding.roleRef.name)
);
this.bindingName = binding.getName();
@ -157,6 +166,10 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
});
createBindings = async () => {
const {
roleBindingStore,
showDetails,
} = this.props;
const { selectedRoleRef, bindingNamespace, selectedBindings, roleBinding, bindingName } = this;
if (!selectedRoleRef || !roleBinding || !bindingNamespace || !bindingName) {
@ -178,7 +191,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
});
showDetails(newRoleBinding.selfLink);
RoleBindingDialog.close();
this.props.closeRoleBindingDialog();
} catch (err) {
Notifications.checkedError(err, `Unknown error occured while ${this.isEditing ? "editing" : "creating"} role bindings.`);
}
@ -260,7 +273,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
}
render() {
const { ...dialogProps } = this.props;
const { closeRoleBindingDialog, roleBindingStore, state, ...dialogProps } = this.props;
const [action, nextLabel] = this.isEditing ? ["Edit", "Update"] : ["Add", "Create"];
const disableNext = !this.selectedRoleRef || !this.selectedBindings.length || !this.bindingNamespace || !this.bindingName;
@ -268,8 +281,8 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
<Dialog
{...dialogProps}
className="AddRoleBindingDialog"
isOpen={RoleBindingDialog.state.isOpen}
close={RoleBindingDialog.close}
isOpen={state.get().isOpen}
close={closeRoleBindingDialog}
onClose={this.reset}
onOpen={this.onOpen}
>
@ -279,7 +292,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
{`${action} RoleBinding`}
</h5>
)}
done={RoleBindingDialog.close}
done={closeRoleBindingDialog}
>
<WizardStep
nextLabel={nextLabel}
@ -293,3 +306,17 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
);
}
}
export const RoleBindingDialog = withInjectables<Dependencies, RoleBindingDialogProps>(NonInjectedRoleBindingDialog, {
getProps: (di, props) => ({
...props,
roleBindingStore: di.inject(roleBindingStoreInjectable),
state: di.inject(roleBindingDialogStateInjectable),
closeRoleBindingDialog: di.inject(closeRoleBindingDialogInjectable),
showDetails: di.inject(showDetailsInjectable),
clusterRoleStore: di.inject(clusterRoleStoreInjectable),
roleStore: di.inject(roleStoreInjectable),
serviceAccountStore: di.inject(serviceAccountStoreInjectable),
roleApi: di.inject(roleApiInjectable),
}),
});

View File

@ -4,4 +4,4 @@
*/
export * from "./view";
export * from "./details";
export * from "./dialog";
export * from "./dialog/view";

View File

@ -8,7 +8,7 @@ import { observer } from "mobx-react";
import React from "react";
import { KubeObjectListLayout } from "../../kube-object-list-layout";
import { KubeObjectStatusIcon } from "../../kube-object-status-icon";
import { RoleBindingDialog } from "./dialog";
import { RoleBindingDialog } from "./dialog/view";
import { SiblingsInTabLayout } from "../../layout/siblings-in-tab-layout";
import { KubeObjectAge } from "../../kube-object/age";
import type { RoleStore } from "../+roles/store";
@ -23,6 +23,8 @@ import filterByNamespaceInjectable from "../../+namespaces/namespace-select-filt
import roleBindingStoreInjectable from "./store.injectable";
import roleStoreInjectable from "../+roles/store.injectable";
import serviceAccountStoreInjectable from "../+service-accounts/store.injectable";
import type { OpenRoleBindingDialog } from "./dialog/open.injectable";
import openRoleBindingDialogInjectable from "./dialog/open.injectable";
enum columnId {
name = "name",
@ -37,6 +39,7 @@ interface Dependencies {
clusterRoleStore: ClusterRoleStore;
serviceAccountStore: ServiceAccountStore;
filterByNamespace: FilterByNamespace;
openRoleBindingDialog: OpenRoleBindingDialog;
}
@observer
@ -48,6 +51,7 @@ class NonInjectedRoleBindings extends React.Component<Dependencies> {
roleStore,
serviceAccountStore,
filterByNamespace,
openRoleBindingDialog,
} = this.props;
return (
@ -90,7 +94,7 @@ class NonInjectedRoleBindings extends React.Component<Dependencies> {
<KubeObjectAge key="age" object={binding} />,
]}
addRemoveButtons={{
onAdd: () => RoleBindingDialog.open(),
onAdd: () => openRoleBindingDialog(),
addTooltip: "Create new RoleBinding",
}}
/>
@ -108,5 +112,6 @@ export const RoleBindings = withInjectables<Dependencies>(NonInjectedRoleBinding
roleBindingStore: di.inject(roleBindingStoreInjectable),
roleStore: di.inject(roleStoreInjectable),
serviceAccountStore: di.inject(serviceAccountStoreInjectable),
openRoleBindingDialog: di.inject(openRoleBindingDialogInjectable),
}),
});