mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Turn on strict mode in tsconfig.json, some helpful lints, and required cleanup where strictness necessitates it (#5195)
* Turn on strict mode in tsconfig.json - Add route, clusterRoute, and payloadValidatedClusterRoute helper functions to improve types with backend routes - Turn on the following new lints: - react/jsx-first-prop-new-line - react/jsx-wrap-multilines - react/jsx-one-expression-per-line - react/jsx-max-props-per-line - react/jsx-indent - react/jsx-indent-props Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix build Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace KubeObject scope strings with enum Signed-off-by: Sebastian Malton <sebastian@malton.name> * Revert package.json version changes Signed-off-by: Sebastian Malton <sebastian@malton.name> * revert move hostedCluster(Id) Signed-off-by: Sebastian Malton <sebastian@malton.name> * change some type param names to be not single letters Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove copy-extension-themes Signed-off-by: Sebastian Malton <sebastian@malton.name> * add new make clean action Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix build to not use webpack for generating types Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix kube-object-menu.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix select.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix catalog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * revert move fileNameMigration to index Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix ref logic error Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix log-resource-selector.test.tsx tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix dock-store.test.ts test by overriding createStorage to not touch file system Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix cluster.test.ts tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix kube=api.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fixed hotbar-store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix kubeconfig-manager.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix cluster-role-bindings/__tests__/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix role-bindings/__tests__/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix pods.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix delete-cluster-dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix daemonset.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix replicaset.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix statefulsets/dialog/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix replicasets/scale-dialog/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix deployments.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix deployments/scale/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix cronjob.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix stateful-set.api.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix deployment.api.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix api-manager.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix statefulset.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix job.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix pods.store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix scroll-spy.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix hotbar-remove-command.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix catalog-entity-registry.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix welcome.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix verify-that-all-routes-have-route-component.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix pod-tolerations.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * better fix for previous 3 fixes, plus also select.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix kube-object-menu.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix app-paths.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix dock-tabs.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix isReactNode typing Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix sub-title.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix drawer.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix list-layout.tsx and header.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix error-boundary.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix upgrade-chart/store.ts and dock-tab.store.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix install-chart/store.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix edit-resource/store.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix create-resource/store.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix namespace-select.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix namespace-select-filter.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix crd-list.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix wrong types for extensions Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix circular dependency Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix circular dependency on catalogCategoryRegistry Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix api-kube Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix type errors, most <Select /> errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * fixing more type errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * some more fixing type errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * convert all KubeApis to injectable with legacy global backups Signed-off-by: Sebastian Malton <sebastian@malton.name> * factor out into a common file all the exports Signed-off-by: Sebastian Malton <sebastian@malton.name> * convert all KubeObjectStores to injectable with legacy global backups Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix lint Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove unused legacy KubeApi globals Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix bad previous commit Signed-off-by: Sebastian Malton <sebastian@malton.name> * more crash fixing Signed-off-by: Sebastian Malton <sebastian@malton.name> * try and fix behavioural tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix sidebar-and-tab-navigation-for-core.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix sidebar-and-tab-navigation-for-extensions.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-using-application-menu.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix catalog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make ThemeStore non-singleton and fix navigation-to-terminal-preferences.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * extensions.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix catalog-entity-registry.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-using-application-menu.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix log-resource-selector.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix dock-tabs.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix delete-cluster-dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-kubernetes-preferences.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-editor-preferences.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-proxy-preferences.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-using-application-menu.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-application-preferences.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix dock-store.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix select.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix role-bindings/__tests__/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix hotbar-remove-command.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix cluster-role-bindings/__tests__/dialog.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-extension-specific-preferences.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-telemetry-preferences.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix closing-preferences.test.tsx Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-editor-preferences.test.ts Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix navigation-to-proxy-preferences.test.ts - Fix other type errors too Signed-off-by: Sebastian Malton <sebastian@malton.name> * final tweaks Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add more tsconfig files, fix bug in <Catalog> - Make all of history, navigation injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix type errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert all of kube-details-params/ and navigate/ to injectable - This fixes a runtime error that was encountered during testing Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix runtime errors on renderer - remove all static uses of `createPageParam` (and then removed the legacy global) - Made LensRendererExtension and LensMainExtension just used dependencies and not the getLegacyDi - Fixed circular dep in extension-loader Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move registerStore calls to after injectMany Signed-off-by: Sebastian Malton <sebastian@malton.name> * replace all the rest of the legacy uses of apiManager Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix stack overflow and cycles in DI Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix NamespaceSelectFilter not opening Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix WizardStep and AddNamespaceDialog Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix KubeApi's not being registered Signed-off-by: Sebastian Malton <sebastian@malton.name> * cleanup WindowManager Signed-off-by: Sebastian Malton <sebastian@malton.name> * Proper fix for Wizard, fix NamespaceStore.subscribe Signed-off-by: Sebastian Malton <sebastian@malton.name> * Rewrite withTooltip to be more type correct - Fixes mobx related "too many recursive actions" error - Change all the uses of withTooltips to be functional components Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add e2e test to cover kube api registration Signed-off-by: Sebastian Malton <sebastian@malton.name> * cleanup internal-commands Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove cast in <Animate> Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix command-palette e2e test Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type error after rebase Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix test name Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix lint Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix code to help CodeQL scanner Signed-off-by: Sebastian Malton <sebastian@malton.name> * update intree extension lock files Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix build-extensions picking wrong @types/react Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix tests from rebase Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix type error Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make KubeconfigSyncManager more injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix crash in test mode for Dialog Signed-off-by: Sebastian Malton <sebastian@malton.name> * make Select snapshots deterministic Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix new type error Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix kube-object.store.test.ts typing Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix merge build issues Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix snapshots after merge Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix lint after merge Signed-off-by: Sebastian Malton <sebastian@malton.name> * reexport BaseKubeJsonApiObjectMetadata Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix typo in terminalSpawningPool Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove duplicate license header Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix typo to waitUntilDefined Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove iter use from getLegacyGlobalDiForExtensionApi Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove complex createStorage override Signed-off-by: Sebastian Malton <sebastian@malton.name> * override logger with mocks only when needed for tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove specialized overrideStore flags for getDiForUnitTesting Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove unnecessary | undefined types from the exactOptionalFieldTypes experiment Signed-off-by: Sebastian Malton <sebastian@malton.name> * use more descriptive name for local test mocks Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove unnecessary addition to 'make clean' target Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove oddity of KubeObjectStore.getById(undefined) being allowed Signed-off-by: Sebastian Malton <sebastian@malton.name> * rename KubeObject.getDescriptor in favour of name without fundemental JS meaning Signed-off-by: Sebastian Malton <sebastian@malton.name> * Simplify legacyRegisterApi when working in behaviour unit tests - Don't emit within main environment as there should be no auto registering there Signed-off-by: Sebastian Malton <sebastian@malton.name> * change confusing variable name in ReactiveDuration Signed-off-by: Sebastian Malton <sebastian@malton.name> * make visitor pattern more explicit for Entity contextMenuOpen Signed-off-by: Sebastian Malton <sebastian@malton.name> * toggleDetails -> toggleKubeDetailsPane is more specific Signed-off-by: Sebastian Malton <sebastian@malton.name> * remove outdated comment Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix bug where LensExtension dependencies are not set Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests from the revert of react 18 Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix more tests from merge Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix typings with new is-compatible-extension tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * more type fixing Signed-off-by: Sebastian Malton <sebastian@malton.name> * Revert in-tree extension versions Signed-off-by: Sebastian Malton <sebastian@malton.name> * Improve name of guarding injectable for stores and apis - New name better implies that it is just a guard state and does not do anything Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add helper for <Select>.isMulti for storing in a Set<Value> Signed-off-by: Sebastian Malton <sebastian@malton.name> * fix is-compatible-extension.test.ts types Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
381d77c633
commit
dfcb7c3330
1062 files changed
+26512
-28689
No files matched your search
@@ -5,16 +5,15 @@
|
||||
|
||||
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 storesAndApisCanBeCreatedInjectable from "../../../../stores-apis-can-be-created.injectable";
|
||||
import ipcRendererInjectable from "../../../../app-paths/get-value-from-registered-channel/ipc-renderer/ipc-renderer.injectable";
|
||||
|
||||
describe("RoleBindingDialog tests", () => {
|
||||
let render: DiRender;
|
||||
@@ -22,21 +21,31 @@ describe("RoleBindingDialog tests", () => {
|
||||
beforeEach(async () => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(ipcRendererInjectable, () => ({
|
||||
on: jest.fn(),
|
||||
invoke: jest.fn(), // TODO: replace with proper mocking via the IPC bridge
|
||||
} as never));
|
||||
|
||||
await di.runSetups();
|
||||
|
||||
render = renderFor(di);
|
||||
|
||||
(clusterRolesStore as any).items = [new ClusterRole({
|
||||
apiVersion: "rbac.authorization.k8s.io/v1",
|
||||
kind: "ClusterRole",
|
||||
metadata: {
|
||||
name: "foobar",
|
||||
resourceVersion: "1",
|
||||
uid: "1",
|
||||
},
|
||||
})];
|
||||
const store = di.inject(clusterRoleStoreInjectable);
|
||||
|
||||
store.items.replace([
|
||||
new ClusterRole({
|
||||
apiVersion: "rbac.authorization.k8s.io/v1",
|
||||
kind: "ClusterRole",
|
||||
metadata: {
|
||||
name: "foobar",
|
||||
resourceVersion: "1",
|
||||
uid: "1",
|
||||
selfLink: "/apis/rbac.authorization.k8s.io/v1/clusterroles/foobar",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import "./details.scss";
|
||||
import { reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import type { RoleBinding, RoleBindingSubject } from "../../../../common/k8s-api/endpoints";
|
||||
import type { RoleBinding } from "../../../../common/k8s-api/endpoints";
|
||||
import { prevDefault } from "../../../utils";
|
||||
import { AddRemoveButtons } from "../../add-remove-buttons";
|
||||
import { DrawerTitle } from "../../drawer";
|
||||
@@ -16,9 +16,9 @@ import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { KubeObjectMeta } from "../../kube-object-meta";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../../table";
|
||||
import { RoleBindingDialog } from "./dialog";
|
||||
import { roleBindingsStore } from "./store";
|
||||
import { roleBindingStore } from "./legacy-store";
|
||||
import { ObservableHashSet } from "../../../../common/utils/hash-set";
|
||||
import { hashRoleBindingSubject } from "./hashers";
|
||||
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";
|
||||
@@ -32,7 +32,7 @@ interface Dependencies {
|
||||
|
||||
@observer
|
||||
class NonInjectedRoleBindingDetails extends React.Component<RoleBindingDetailsProps & Dependencies> {
|
||||
selectedSubjects = new ObservableHashSet<RoleBindingSubject>([], hashRoleBindingSubject);
|
||||
private readonly selectedSubjects = new ObservableHashSet([], hashSubject);
|
||||
|
||||
async componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
@@ -47,10 +47,14 @@ class NonInjectedRoleBindingDetails extends React.Component<RoleBindingDetailsPr
|
||||
const { selectedSubjects } = this;
|
||||
|
||||
openConfirmDialog({
|
||||
ok: () => roleBindingsStore.removeSubjects(roleBinding, selectedSubjects.toJSON()),
|
||||
ok: () => roleBindingStore.removeSubjects(roleBinding, selectedSubjects.toJSON()),
|
||||
labelOk: `Remove`,
|
||||
message: (
|
||||
<p>Remove selected bindings for <b>{roleBinding.getName()}</b>?</p>
|
||||
<p>
|
||||
Remove selected bindings for
|
||||
<b>{roleBinding.getName()}</b>
|
||||
?
|
||||
</p>
|
||||
),
|
||||
});
|
||||
};
|
||||
@@ -116,7 +120,7 @@ class NonInjectedRoleBindingDetails extends React.Component<RoleBindingDetailsPr
|
||||
|
||||
<AddRemoveButtons
|
||||
onAdd={() => RoleBindingDialog.open(roleBinding)}
|
||||
onRemove={selectedSubjects.size ? this.removeSelectedSubjects : null}
|
||||
onRemove={selectedSubjects.size ? this.removeSelectedSubjects : undefined}
|
||||
addTooltip={`Edit bindings of ${roleRef.name}`}
|
||||
removeTooltip={`Remove selected bindings from ${roleRef.name}`}
|
||||
/>
|
||||
|
||||
@@ -9,10 +9,10 @@ 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, RoleBindingSubject, ServiceAccount } from "../../../../common/k8s-api/endpoints";
|
||||
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";
|
||||
@@ -22,12 +22,13 @@ import { showDetails } from "../../kube-detail-params";
|
||||
import { SubTitle } from "../../layout/sub-title";
|
||||
import { Notifications } from "../../notifications";
|
||||
import type { SelectOption } from "../../select";
|
||||
import { Select } from "../../select";
|
||||
import { onMultiSelectFor, Select } from "../../select";
|
||||
import { Wizard, WizardStep } from "../../wizard";
|
||||
import { roleBindingsStore } from "./store";
|
||||
import { clusterRolesStore } from "../+cluster-roles/store";
|
||||
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";
|
||||
|
||||
export interface RoleBindingDialogProps extends Partial<DialogProps> {
|
||||
}
|
||||
@@ -58,7 +59,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
RoleBindingDialog.state.data = undefined;
|
||||
}
|
||||
|
||||
get roleBinding(): RoleBinding {
|
||||
get roleBinding() {
|
||||
return RoleBindingDialog.state.data;
|
||||
}
|
||||
|
||||
@@ -66,26 +67,26 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
return !!this.roleBinding;
|
||||
}
|
||||
|
||||
@observable.ref selectedRoleRef: Role | ClusterRole | undefined = undefined;
|
||||
@observable.ref selectedRoleRef: Role | ClusterRole | null | undefined = null;
|
||||
@observable bindingName = "";
|
||||
@observable bindingNamespace = "";
|
||||
@observable bindingNamespace: string | null = null;
|
||||
selectedAccounts = new ObservableHashSet<ServiceAccount>([], sa => sa.metadata.uid);
|
||||
selectedUsers = observable.set<string>([]);
|
||||
selectedGroups = observable.set<string>([]);
|
||||
|
||||
@computed get selectedBindings(): RoleBindingSubject[] {
|
||||
const serviceAccounts = Array.from(this.selectedAccounts, sa => ({
|
||||
@computed get selectedBindings(): Subject[] {
|
||||
const serviceAccounts: Subject[] = Array.from(this.selectedAccounts, sa => ({
|
||||
name: sa.getName(),
|
||||
kind: "ServiceAccount" as const,
|
||||
kind: "ServiceAccount",
|
||||
namespace: sa.getNs(),
|
||||
}));
|
||||
const users = Array.from(this.selectedUsers, user => ({
|
||||
const users: Subject[] = Array.from(this.selectedUsers, user => ({
|
||||
name: user,
|
||||
kind: "User" as const,
|
||||
kind: "User",
|
||||
}));
|
||||
const groups = Array.from(this.selectedGroups, group => ({
|
||||
const groups: Subject[] = Array.from(this.selectedGroups, group => ({
|
||||
name: group,
|
||||
kind: "Group" as const,
|
||||
kind: "Group",
|
||||
}));
|
||||
|
||||
return [
|
||||
@@ -96,27 +97,25 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
}
|
||||
|
||||
@computed get roleRefOptions(): SelectOption<Role | ClusterRole>[] {
|
||||
const roles = rolesStore.items
|
||||
.filter(role => role.getNs() === this.bindingNamespace)
|
||||
.map(value => ({ value, label: value.getName() }));
|
||||
const clusterRoles = clusterRolesStore.items
|
||||
.map(value => ({ value, label: value.getName() }));
|
||||
const roles = roleStore.items
|
||||
.filter(role => role.getNs() === this.bindingNamespace);
|
||||
const clusterRoles = clusterRoleStore.items;
|
||||
|
||||
return [
|
||||
...roles,
|
||||
...clusterRoles,
|
||||
];
|
||||
}
|
||||
|
||||
@computed get serviceAccountOptions(): SelectOption<ServiceAccount>[] {
|
||||
return serviceAccountsStore.items.map(account => ({
|
||||
value: account,
|
||||
label: `${account.getName()} (${account.getNs()})`,
|
||||
].map(r => ({
|
||||
value: r,
|
||||
label: r.getName(),
|
||||
}));
|
||||
}
|
||||
|
||||
@computed get selectedServiceAccountOptions(): SelectOption<ServiceAccount>[] {
|
||||
return this.serviceAccountOptions.filter(({ value }) => this.selectedAccounts.has(value));
|
||||
@computed get serviceAccountOptions(): SelectOption<ServiceAccount>[] {
|
||||
return serviceAccountStore.items.map(serviceAccount => ({
|
||||
value: serviceAccount,
|
||||
label: `${serviceAccount.getName()} (${serviceAccount.getNs()})`,
|
||||
isSelected: this.selectedAccounts.has(serviceAccount),
|
||||
}));
|
||||
}
|
||||
|
||||
onOpen = action(() => {
|
||||
@@ -126,9 +125,13 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
return this.reset();
|
||||
}
|
||||
|
||||
this.selectedRoleRef = (binding.roleRef.kind === roleApi.kind ? rolesStore : clusterRolesStore)
|
||||
.items
|
||||
.find(item => item.getName() === binding.roleRef.name);
|
||||
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)
|
||||
);
|
||||
|
||||
this.bindingName = binding.getName();
|
||||
this.bindingNamespace = binding.getNs();
|
||||
@@ -137,7 +140,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
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));
|
||||
@@ -145,7 +148,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
});
|
||||
|
||||
reset = action(() => {
|
||||
this.selectedRoleRef = undefined;
|
||||
this.selectedRoleRef = null;
|
||||
this.bindingName = "";
|
||||
this.bindingNamespace = "";
|
||||
this.selectedAccounts.clear();
|
||||
@@ -154,12 +157,19 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
});
|
||||
|
||||
createBindings = async () => {
|
||||
const { selectedRoleRef, bindingNamespace: namespace, selectedBindings } = this;
|
||||
const { selectedRoleRef, bindingNamespace, selectedBindings, roleBinding, bindingName } = this;
|
||||
|
||||
if (!selectedRoleRef || !roleBinding || !bindingNamespace || !bindingName) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const roleBinding = this.isEditing
|
||||
? await roleBindingsStore.updateSubjects(this.roleBinding, selectedBindings)
|
||||
: await roleBindingsStore.create({ name: this.bindingName, namespace }, {
|
||||
const newRoleBinding = this.isEditing
|
||||
? await roleBindingStore.updateSubjects(roleBinding, selectedBindings)
|
||||
: await roleBindingStore.create({
|
||||
name: bindingName,
|
||||
namespace: bindingNamespace,
|
||||
}, {
|
||||
subjects: selectedBindings,
|
||||
roleRef: {
|
||||
name: selectedRoleRef.getName(),
|
||||
@@ -167,10 +177,10 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
},
|
||||
});
|
||||
|
||||
showDetails(roleBinding.selfLink);
|
||||
showDetails(newRoleBinding.selfLink);
|
||||
RoleBindingDialog.close();
|
||||
} catch (err) {
|
||||
Notifications.error(err);
|
||||
Notifications.checkedError(err, `Unknown error occured while ${this.isEditing ? "editing" : "creating"} role bindings.`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -184,7 +194,7 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
isDisabled={this.isEditing}
|
||||
value={this.bindingNamespace}
|
||||
autoFocus={!this.isEditing}
|
||||
onChange={({ value }) => this.bindingNamespace = value}
|
||||
onChange={opt => this.bindingNamespace = opt?.value ?? null}
|
||||
/>
|
||||
|
||||
<SubTitle title="Role Reference" />
|
||||
@@ -195,12 +205,12 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
isDisabled={this.isEditing}
|
||||
options={this.roleRefOptions}
|
||||
value={this.selectedRoleRef}
|
||||
onChange={({ value }) => {
|
||||
if (!this.selectedRoleRef || this.bindingName === this.selectedRoleRef.getName()) {
|
||||
this.bindingName = value.getName();
|
||||
}
|
||||
onChange={option => {
|
||||
this.selectedRoleRef = option?.value;
|
||||
|
||||
this.selectedRoleRef = value;
|
||||
if (!this.selectedRoleRef || this.bindingName === this.selectedRoleRef.getName()) {
|
||||
this.bindingName = option?.value.getName() ?? "";
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -235,19 +245,14 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
isMulti
|
||||
themeName="light"
|
||||
placeholder="Select service accounts ..."
|
||||
autoConvertOptions={false}
|
||||
options={this.serviceAccountOptions}
|
||||
value={this.selectedServiceAccountOptions}
|
||||
formatOptionLabel={({ value }: SelectOption<ServiceAccount>) => (
|
||||
<><Icon small material="account_box" /> {value.getName()} ({value.getNs()})</>
|
||||
formatOptionLabel={option => (
|
||||
<>
|
||||
<Icon small material="account_box" />
|
||||
{` ${option.label}`}
|
||||
</>
|
||||
)}
|
||||
onChange={(selected: SelectOption<ServiceAccount>[] | null) => {
|
||||
if (selected) {
|
||||
this.selectedAccounts.replace(selected.map(opt => opt.value));
|
||||
} else {
|
||||
this.selectedAccounts.clear();
|
||||
}
|
||||
}}
|
||||
onChange={onMultiSelectFor(this.selectedAccounts)}
|
||||
maxMenuHeight={200}
|
||||
/>
|
||||
</>
|
||||
@@ -269,7 +274,11 @@ export class RoleBindingDialog extends React.Component<RoleBindingDialogProps> {
|
||||
onOpen={this.onOpen}
|
||||
>
|
||||
<Wizard
|
||||
header={<h5>{action} RoleBinding</h5>}
|
||||
header={(
|
||||
<h5>
|
||||
{`${action} RoleBinding`}
|
||||
</h5>
|
||||
)}
|
||||
done={RoleBindingDialog.close}
|
||||
>
|
||||
<WizardStep
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { MD5 } from "crypto-js";
|
||||
import type { RoleBindingSubject } from "../../../../common/k8s-api/endpoints";
|
||||
|
||||
export function hashRoleBindingSubject(subject: RoleBindingSubject): string {
|
||||
return MD5(JSON.stringify([
|
||||
["kind", subject.kind],
|
||||
["name", subject.name],
|
||||
["namespace", subject.namespace],
|
||||
["apiGroup", subject.apiGroup],
|
||||
])).toString();
|
||||
}
|
||||
@@ -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 roleBindingStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(roleBindingStoreInjectable)` instead
|
||||
*/
|
||||
export const roleBindingStore = asLegacyGlobalForExtensionApi(roleBindingStoreInjectable);
|
||||
@@ -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 assert from "assert";
|
||||
import { kubeObjectStoreInjectionToken } from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import roleBindingApiInjectable from "../../../../common/k8s-api/endpoints/role-binding.api.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../stores-apis-can-be-created.injectable";
|
||||
import { RoleBindingStore } from "./store";
|
||||
|
||||
const roleBindingStoreInjectable = getInjectable({
|
||||
id: "role-binding-store",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectable), "roleBindingStore is only available in certain environments");
|
||||
|
||||
const api = di.inject(roleBindingApiInjectable);
|
||||
|
||||
return new RoleBindingStore(api);
|
||||
},
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
});
|
||||
|
||||
export default roleBindingStoreInjectable;
|
||||
@@ -3,16 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { apiManager } from "../../../../common/k8s-api/api-manager";
|
||||
import type { RoleBinding, RoleBindingSubject } from "../../../../common/k8s-api/endpoints";
|
||||
import { roleBindingApi } from "../../../../common/k8s-api/endpoints";
|
||||
import type { RoleBinding, RoleBindingApi, RoleBindingData } from "../../../../common/k8s-api/endpoints";
|
||||
import type { Subject } from "../../../../common/k8s-api/endpoints/types/subject";
|
||||
import { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store";
|
||||
import { HashSet } from "../../../utils";
|
||||
import { hashRoleBindingSubject } from "./hashers";
|
||||
|
||||
export class RoleBindingsStore extends KubeObjectStore<RoleBinding> {
|
||||
api = roleBindingApi;
|
||||
import { hashSubject } from "../hashers";
|
||||
|
||||
export class RoleBindingStore extends KubeObjectStore<RoleBinding, RoleBindingApi, RoleBindingData> {
|
||||
protected sortItems(items: RoleBinding[]) {
|
||||
return super.sortItems(items, [
|
||||
roleBinding => roleBinding.kind,
|
||||
@@ -20,19 +17,15 @@ export class RoleBindingsStore extends KubeObjectStore<RoleBinding> {
|
||||
]);
|
||||
}
|
||||
|
||||
protected async createItem(params: { name: string; namespace: string }, data?: Partial<RoleBinding>) {
|
||||
return roleBindingApi.create(params, data);
|
||||
}
|
||||
|
||||
async updateSubjects(roleBinding: RoleBinding, subjects: RoleBindingSubject[]) {
|
||||
async updateSubjects(roleBinding: RoleBinding, subjects: Subject[]) {
|
||||
return this.update(roleBinding, {
|
||||
roleRef: roleBinding.roleRef,
|
||||
subjects,
|
||||
});
|
||||
}
|
||||
|
||||
async removeSubjects(roleBinding: RoleBinding, subjectsToRemove: Iterable<RoleBindingSubject>) {
|
||||
const currentSubjects = new HashSet(roleBinding.getSubjects(), hashRoleBindingSubject);
|
||||
async removeSubjects(roleBinding: RoleBinding, subjectsToRemove: Iterable<Subject>) {
|
||||
const currentSubjects = new HashSet(roleBinding.getSubjects(), hashSubject);
|
||||
|
||||
for (const subject of subjectsToRemove) {
|
||||
currentSubjects.delete(subject);
|
||||
@@ -41,7 +34,3 @@ export class RoleBindingsStore extends KubeObjectStore<RoleBinding> {
|
||||
return this.updateSubjects(roleBinding, currentSubjects.toJSON());
|
||||
}
|
||||
}
|
||||
|
||||
export const roleBindingsStore = new RoleBindingsStore();
|
||||
|
||||
apiManager.registerStore(roleBindingsStore);
|
||||
@@ -9,10 +9,10 @@ import React from "react";
|
||||
import { KubeObjectListLayout } from "../../kube-object-list-layout";
|
||||
import { KubeObjectStatusIcon } from "../../kube-object-status-icon";
|
||||
import { RoleBindingDialog } from "./dialog";
|
||||
import { roleBindingsStore } from "./store";
|
||||
import { rolesStore } from "../+roles/store";
|
||||
import { clusterRolesStore } from "../+cluster-roles/store";
|
||||
import { serviceAccountsStore } from "../+service-accounts/store";
|
||||
import { roleBindingStore } from "./legacy-store";
|
||||
import { roleStore } from "../+roles/legacy-store";
|
||||
import { clusterRoleStore } from "../+cluster-roles/legacy-store";
|
||||
import { serviceAccountStore } from "../+service-accounts/legacy-store";
|
||||
import { SiblingsInTabLayout } from "../../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../../kube-object/age";
|
||||
|
||||
@@ -32,8 +32,8 @@ export class RoleBindings extends React.Component {
|
||||
isConfigurable
|
||||
tableId="access_role_bindings"
|
||||
className="RoleBindings"
|
||||
store={roleBindingsStore}
|
||||
dependentStores={[rolesStore, clusterRolesStore, serviceAccountsStore]}
|
||||
store={roleBindingStore}
|
||||
dependentStores={[roleStore, clusterRoleStore, serviceAccountStore]}
|
||||
sortingCallbacks={{
|
||||
[columnId.name]: binding => binding.getName(),
|
||||
[columnId.namespace]: binding => binding.getNs(),
|
||||
|
||||
Reference in new issue
Block a user