diff --git a/web-app/src/common/SecureComponent/permissions.ts b/web-app/src/common/SecureComponent/permissions.ts index 8a68e37b6..45593aa5f 100644 --- a/web-app/src/common/SecureComponent/permissions.ts +++ b/web-app/src/common/SecureComponent/permissions.ts @@ -173,7 +173,6 @@ export const IAM_PAGES = { TOOLS_AUDITLOGS: "/tools/audit-logs", TOOLS_TRACE: "/tools/trace", DASHBOARD: "/tools/metrics", - TOOLS_HEAL: "/tools/heal", TOOLS_WATCH: "/tools/watch", /* KMS */ @@ -402,7 +401,6 @@ export const IAM_PAGES_PERMISSIONS = { IAM_SCOPES.S3_LISTEN_BUCKET_NOTIFICATIONS, // display watch notifications ], [IAM_PAGES.TOOLS_TRACE]: [IAM_SCOPES.ADMIN_SERVER_TRACE], - [IAM_PAGES.TOOLS_HEAL]: [IAM_SCOPES.ADMIN_HEAL], [IAM_PAGES.TOOLS_DIAGNOSTICS]: [ IAM_SCOPES.ADMIN_HEALTH_INFO, IAM_SCOPES.ADMIN_SERVER_INFO, diff --git a/web-app/src/screens/Console/Console.tsx b/web-app/src/screens/Console/Console.tsx index 3d79e84f5..a06fb31a3 100644 --- a/web-app/src/screens/Console/Console.tsx +++ b/web-app/src/screens/Console/Console.tsx @@ -50,7 +50,6 @@ import LoadingComponent from "../../common/LoadingComponent"; import ComponentsScreen from "./Common/ComponentsScreen"; const Trace = React.lazy(() => import("./Trace/Trace")); -const Heal = React.lazy(() => import("./Heal/Heal")); const Watch = React.lazy(() => import("./Watch/Watch")); const HealthInfo = React.lazy(() => import("./HealthInfo/HealthInfo")); @@ -324,10 +323,6 @@ const Console = () => { component: IDPOpenIDConfigurationDetails, path: IAM_PAGES.IDP_OPENID_CONFIGURATIONS_VIEW, }, - { - component: Heal, - path: IAM_PAGES.TOOLS_HEAL, - }, { component: Trace, path: IAM_PAGES.TOOLS_TRACE, diff --git a/web-app/src/screens/Console/Heal/Heal.tsx b/web-app/src/screens/Console/Heal/Heal.tsx deleted file mode 100644 index 48eab714c..000000000 --- a/web-app/src/screens/Console/Heal/Heal.tsx +++ /dev/null @@ -1,381 +0,0 @@ -// This file is part of MinIO Console Server -// Copyright (c) 2021 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -import React, { Fragment, useEffect, useState } from "react"; -import { useSelector } from "react-redux"; -import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket"; -import { - Box, - Button, - Checkbox, - Grid, - HealIcon, - InputBox, - InputLabel, - PageLayout, - Select, -} from "mds"; -import { - Bar, - BarChart, - CartesianGrid, - Legend, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis, -} from "recharts"; - -import { api } from "api"; -import { Bucket } from "api/consoleApi"; -import { errorToHandler } from "api/errors"; -import { wsProtocol } from "../../../utils/wsUtils"; -import { colorH, HealStatus } from "./types"; -import { niceBytes } from "../../../common/utils"; -import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary"; -import { - CONSOLE_UI_RESOURCE, - IAM_SCOPES, -} from "../../../common/SecureComponent/permissions"; -import { selDistSet, setHelpName } from "../../../systemSlice"; -import { SecureComponent } from "../../../common/SecureComponent"; -import { useAppDispatch } from "../../../store"; -import DistributedOnly from "../Common/DistributedOnly/DistributedOnly"; -import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper"; -import HelpMenu from "../HelpMenu"; - -const Heal = () => { - const distributedSetup = useSelector(selDistSet); - - const [start, setStart] = useState(false); - const [bucketName, setBucketName] = useState(""); - const [bucketList, setBucketList] = useState([]); - const [prefix, setPrefix] = useState(""); - const [recursive, setRecursive] = useState(false); - const [forceStart, setForceStart] = useState(false); - const [forceStop, setForceStop] = useState(false); - // healStatus states - const [hStatus, setHStatus] = useState({ - beforeHeal: [0, 0, 0, 0], - afterHeal: [0, 0, 0, 0], - objectsHealed: 0, - objectsScanned: 0, - healDuration: 0, - sizeScanned: "", - }); - - const fetchBucketList = () => { - api.buckets - .listBuckets() - .then((res) => { - let buckets: Bucket[] = []; - if (res.data.buckets) { - buckets = res.data.buckets; - } - setBucketList(buckets); - }) - .catch((err) => { - console.error(errorToHandler(err.error)); - }); - }; - - useEffect(() => { - fetchBucketList(); - }, []); - - // forceStart and forceStop need to be mutually exclusive - useEffect(() => { - if (forceStart) { - setForceStop(false); - } - }, [forceStart]); - - useEffect(() => { - if (forceStop) { - setForceStart(false); - } - }, [forceStop]); - - const colorHealthArr = (color: colorH) => { - return [color.Green, color.Yellow, color.Red, color.Grey]; - }; - - useEffect(() => { - // begin watch if bucketName in bucketList and start pressed - if (start) { - // values stored here to update chart - const cB: colorH = { Green: 0, Yellow: 0, Red: 0, Grey: 0 }; - const cA: colorH = { Green: 0, Yellow: 0, Red: 0, Grey: 0 }; - - const url = new URL(window.location.toString()); - const isDev = process.env.NODE_ENV === "development"; - const port = isDev ? "9090" : url.port; - - // check if we are using base path, if not this always is `/` - const baseLocation = new URL(document.baseURI); - const baseUrl = baseLocation.pathname; - - const wsProt = wsProtocol(url.protocol); - const c = new W3CWebSocket( - `${wsProt}://${url.hostname}:${port}${baseUrl}ws/heal/${bucketName}?prefix=${prefix}&recursive=${recursive}&force-start=${forceStart}&force-stop=${forceStop}`, - ); - - if (c !== null) { - c.onopen = () => { - console.log("WebSocket Client Connected"); - c.send("ok"); - }; - c.onmessage = (message: IMessageEvent) => { - let m: HealStatus = JSON.parse(message.data.toString()); - // Store percentage per health color - for (const [key, value] of Object.entries(m.healthAfterCols)) { - cA[key] = (value * 100) / m.itemsScanned; - } - for (const [key, value] of Object.entries(m.healthBeforeCols)) { - cB[key] = (value * 100) / m.itemsScanned; - } - setHStatus({ - beforeHeal: colorHealthArr(cB), - afterHeal: colorHealthArr(cA), - objectsHealed: m.objectsHealed, - objectsScanned: m.objectsScanned, - healDuration: m.healDuration, - sizeScanned: niceBytes(m.bytesScanned.toString()), - }); - }; - c.onclose = () => { - setStart(false); - console.log("connection closed by server"); - }; - return () => { - // close websocket on useEffect cleanup - c.close(1000); - console.log("closing websockets"); - }; - } - } - }, [start, bucketName, forceStart, forceStop, prefix, recursive]); - - let data = [ - { - name: "Green", - ah: hStatus.afterHeal[0], - bh: hStatus.beforeHeal[0], - amt: 100, - }, - { - name: "Yellow", - ah: hStatus.afterHeal[1], - bh: hStatus.beforeHeal[1], - amt: 100, - }, - { - name: "Red", - ah: hStatus.afterHeal[2], - bh: hStatus.beforeHeal[2], - amt: 100, - }, - { - name: "Grey", - ah: hStatus.afterHeal[3], - bh: hStatus.beforeHeal[3], - amt: 100, - }, - ]; - const bucketNames = bucketList.map((bucketName) => ({ - label: bucketName.name, - value: bucketName.name, - })); - const dispatch = useAppDispatch(); - useEffect(() => { - dispatch(setHelpName("heal")); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( - - } /> - - - {!distributedSetup ? ( - } /> - ) : ( - - - - - Bucket -