Fix tenant details screen (#277)
This commit is contained in:
@@ -36,7 +36,7 @@ var (
|
||||
bucketsDetail = "/buckets/:bucketName"
|
||||
serviceAccounts = "/service-accounts"
|
||||
tenants = "/tenants"
|
||||
tenantsDetail = "/tenants/:tenantName"
|
||||
tenantsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName"
|
||||
heal = "/heal"
|
||||
)
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ export const getBytes = (
|
||||
|
||||
const powFactor = unitsTake.findIndex((element) => element === unit);
|
||||
|
||||
if (powFactor == -1) {
|
||||
if (powFactor === -1) {
|
||||
return "0";
|
||||
}
|
||||
const factor = Math.pow(1024, powFactor);
|
||||
|
||||
@@ -311,7 +311,7 @@ const Console = ({
|
||||
},
|
||||
{
|
||||
component: TenantDetails,
|
||||
path: "/tenants/:tenantName",
|
||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName",
|
||||
},
|
||||
];
|
||||
const allowedRoutes = routes.filter((route: any) => allowedPages[route.path]);
|
||||
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
} from "../../../../common/utils";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
IValidation
|
||||
} from "../../../../utils/validationFunctions";
|
||||
import GenericWizard from "../../Common/GenericWizard/GenericWizard";
|
||||
import { IWizardElement } from "../../Common/GenericWizard/types";
|
||||
@@ -65,19 +65,19 @@ interface IAddTenantProps {
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red",
|
||||
color: "red"
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
textAlign: "right"
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const,
|
||||
justifyContent: "flex-start" as const
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8,
|
||||
alignSelf: "flex-start" as const,
|
||||
alignSelf: "flex-start" as const
|
||||
},
|
||||
headerElement: {
|
||||
position: "sticky",
|
||||
@@ -85,16 +85,16 @@ const styles = (theme: Theme) =>
|
||||
paddingTop: 5,
|
||||
marginBottom: 10,
|
||||
backgroundColor: "#fff",
|
||||
zIndex: 500,
|
||||
zIndex: 500
|
||||
},
|
||||
tableTitle: {
|
||||
fontWeight: 700,
|
||||
width: "30%",
|
||||
width: "30%"
|
||||
},
|
||||
zoneError: {
|
||||
color: "#dc1f2e",
|
||||
fontSize: "0.75rem",
|
||||
paddingLeft: 120,
|
||||
paddingLeft: 120
|
||||
},
|
||||
error: {
|
||||
color: "#dc1f2e",
|
||||
@@ -111,7 +111,7 @@ interface Opts {
|
||||
const AddTenant = ({
|
||||
open,
|
||||
closeModalAndRefresh,
|
||||
classes,
|
||||
classes
|
||||
}: IAddTenantProps) => {
|
||||
// Fields
|
||||
const [addSending, setAddSending] = useState<boolean>(false);
|
||||
@@ -301,8 +301,8 @@ const AddTenant = ({
|
||||
|
||||
setNameTenantValid(
|
||||
!("tenant-name" in commonValidation) &&
|
||||
!("namespace" in commonValidation) &&
|
||||
storageClasses.length > 0
|
||||
!("namespace" in commonValidation) &&
|
||||
storageClasses.length > 0
|
||||
);
|
||||
|
||||
setValidationErrors(commonValidation);
|
||||
@@ -337,9 +337,9 @@ const AddTenant = ({
|
||||
|
||||
setConfigValid(
|
||||
!("nodes" in commonValidation) &&
|
||||
!("volume_size" in commonValidation) &&
|
||||
!("memory_per_node" in commonValidation) &&
|
||||
distribution.error === ""
|
||||
!("volume_size" in commonValidation) &&
|
||||
!("memory_per_node" in commonValidation) &&
|
||||
distribution.error === ""
|
||||
);
|
||||
|
||||
setValidationErrors(commonValidation);
|
||||
@@ -356,8 +356,8 @@ const AddTenant = ({
|
||||
required: true,
|
||||
value: imageName,
|
||||
pattern: /^((.*?)\/(.*?):(.+))$/,
|
||||
customPatternMessage: "Format must be of form: 'minio/minio:VERSION'",
|
||||
},
|
||||
customPatternMessage: "Format must be of form: 'minio/minio:VERSION'"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -620,7 +620,7 @@ const AddTenant = ({
|
||||
enabled: true,
|
||||
action: () => {
|
||||
closeModalAndRefresh(false, null);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const wizardSteps: IWizardElement[] = [
|
||||
@@ -690,7 +690,7 @@ const AddTenant = ({
|
||||
id="adv_mode"
|
||||
name="adv_mode"
|
||||
checked={advancedMode}
|
||||
onChange={(e) => {
|
||||
onChange={e => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
|
||||
@@ -703,8 +703,8 @@ const AddTenant = ({
|
||||
),
|
||||
buttons: [
|
||||
cancelButton,
|
||||
{ label: "Next", type: "next", enabled: nameTenantValid },
|
||||
],
|
||||
{ label: "Next", type: "next", enabled: nameTenantValid }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Configure",
|
||||
@@ -1080,8 +1080,8 @@ const AddTenant = ({
|
||||
buttons: [
|
||||
cancelButton,
|
||||
{ label: "Back", type: "back", enabled: true },
|
||||
{ label: "Next", type: "next", enabled: true },
|
||||
],
|
||||
{ label: "Next", type: "next", enabled: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Encryption",
|
||||
@@ -1504,8 +1504,8 @@ const AddTenant = ({
|
||||
buttons: [
|
||||
cancelButton,
|
||||
{ label: "Back", type: "back", enabled: true },
|
||||
{ label: "Next", type: "next", enabled: true },
|
||||
],
|
||||
{ label: "Next", type: "next", enabled: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Tenant Size",
|
||||
@@ -1720,16 +1720,16 @@ const AddTenant = ({
|
||||
enabled: !addSending,
|
||||
action: () => {
|
||||
setAddSending(true);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
let filteredWizardSteps = wizardSteps;
|
||||
|
||||
if (!advancedMode) {
|
||||
filteredWizardSteps = wizardSteps.filter((step) => !step.advancedOnly);
|
||||
filteredWizardSteps = wizardSteps.filter(step => !step.advancedOnly);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -27,11 +27,12 @@ import {
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import api from "../../../../common/api";
|
||||
import { ITenant } from "./types";
|
||||
|
||||
interface IDeleteTenant {
|
||||
classes: any;
|
||||
deleteOpen: boolean;
|
||||
selectedTenant: string;
|
||||
selectedTenant: ITenant;
|
||||
closeDeleteModalAndRefresh: (refreshList: boolean) => any;
|
||||
}
|
||||
|
||||
@@ -54,7 +55,10 @@ const DeleteTenant = ({
|
||||
useEffect(() => {
|
||||
if (deleteLoading) {
|
||||
api
|
||||
.invoke("DELETE", `/api/v1/tenants/${selectedTenant}`)
|
||||
.invoke(
|
||||
"DELETE",
|
||||
`/api/v1/namespaces/${selectedTenant.namespace}/tenants/${selectedTenant.name}`
|
||||
)
|
||||
.then(() => {
|
||||
setDeleteLoading(false);
|
||||
setDeleteError("");
|
||||
@@ -85,7 +89,7 @@ const DeleteTenant = ({
|
||||
<DialogContent>
|
||||
{deleteLoading && <LinearProgress />}
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Are you sure you want to delete tenant <b>{selectedTenant}</b>?
|
||||
Are you sure you want to delete tenant <b>{selectedTenant.name}</b>?
|
||||
{deleteError !== "" && (
|
||||
<React.Fragment>
|
||||
<br />
|
||||
|
||||
@@ -32,6 +32,7 @@ import DeleteTenant from "./DeleteTenant";
|
||||
import AddTenant from "./AddTenant";
|
||||
import { NewServiceAccount } from "../../Common/CredentialsPrompt/types";
|
||||
import CredentialsPrompt from "../../Common/CredentialsPrompt/CredentialsPrompt";
|
||||
import history from "../../../../history";
|
||||
|
||||
interface ITenantsList {
|
||||
classes: any;
|
||||
@@ -122,11 +123,16 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
}
|
||||
};
|
||||
|
||||
const confirmDeleteTenant = (tenant: string) => {
|
||||
const confirmDeleteTenant = (tenant: ITenant) => {
|
||||
setSelectedTenant(tenant);
|
||||
setDeleteOpen(true);
|
||||
};
|
||||
|
||||
const redirectToTenantDetails = (tenant: ITenant) => {
|
||||
history.push(`/namespaces/${tenant.namespace}/tenants/${tenant.name}`);
|
||||
return;
|
||||
};
|
||||
|
||||
const closeCredentialsModal = () => {
|
||||
setShowNewCredentials(false);
|
||||
setCreatedAccount(null);
|
||||
@@ -149,8 +155,8 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
};
|
||||
|
||||
const tableActions = [
|
||||
{ type: "view", to: `/tenants`, sendOnlyId: true },
|
||||
{ type: "delete", onClick: confirmDeleteTenant, sendOnlyId: true },
|
||||
{ type: "view", onClick: redirectToTenantDetails },
|
||||
{ type: "delete", onClick: confirmDeleteTenant },
|
||||
];
|
||||
|
||||
const filteredRecords = records
|
||||
@@ -187,9 +193,7 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
}
|
||||
|
||||
for (let i = 0; i < resTenants.length; i++) {
|
||||
const total =
|
||||
resTenants[i].volume_count * resTenants[i].volume_size;
|
||||
resTenants[i].capacity = niceBytes(total + "");
|
||||
resTenants[i].capacity = niceBytes(resTenants[i].total_size + "");
|
||||
}
|
||||
|
||||
setRecords(resTenants);
|
||||
|
||||
@@ -86,7 +86,14 @@ const ZonesMultiSelector = ({
|
||||
onChange,
|
||||
classes,
|
||||
}: IZonesMultiSelector) => {
|
||||
const defaultZone: IZone = { name: "", servers: 0, capacity: "", volumes: 0 };
|
||||
const defaultZone: IZone = {
|
||||
name: "",
|
||||
servers: 0,
|
||||
capacity: "",
|
||||
volumes: 0,
|
||||
volumes_per_server: 0,
|
||||
volume_configuration: { size: 0, storage_class: "", labels: null },
|
||||
};
|
||||
|
||||
const [currentElements, setCurrentElements] = useState<IZone[]>([]);
|
||||
const [internalCounter, setInternalCounter] = useState<number>(1);
|
||||
|
||||
@@ -17,18 +17,32 @@
|
||||
export interface IZone {
|
||||
name: string;
|
||||
servers: number;
|
||||
volumes_per_server: number;
|
||||
volume_configuration: IVolumeConfiguration;
|
||||
// computed
|
||||
capacity: string;
|
||||
volumes: number;
|
||||
}
|
||||
|
||||
export interface IAddZoneRequest {
|
||||
name: string;
|
||||
servers: number;
|
||||
volumes_per_server: number;
|
||||
volume_configuration: IVolumeConfiguration;
|
||||
}
|
||||
|
||||
export interface IVolumeConfiguration {
|
||||
size: number;
|
||||
storage_class: string;
|
||||
labels: { [key: string]: any } | null;
|
||||
}
|
||||
|
||||
export interface ITenant {
|
||||
total_size: number;
|
||||
name: string;
|
||||
namespace: string;
|
||||
image: string;
|
||||
console_image: string;
|
||||
zone_count: number;
|
||||
currentState: string;
|
||||
instance_count: 4;
|
||||
|
||||
@@ -8,33 +8,34 @@ import Grid from "@material-ui/core/Grid";
|
||||
import {
|
||||
factorForDropdown,
|
||||
getTotalSize,
|
||||
niceBytes,
|
||||
niceBytes
|
||||
} from "../../../../common/utils";
|
||||
import { Button, LinearProgress } from "@material-ui/core";
|
||||
import api from "../../../../common/api";
|
||||
import { IAddZoneRequest, ITenant } from "../ListTenants/types";
|
||||
|
||||
interface IAddZoneProps {
|
||||
tenant: ITenant;
|
||||
classes: any;
|
||||
open: boolean;
|
||||
onCloseZoneAndReload: (shouldReload: boolean) => void;
|
||||
volumesPerInstance: number;
|
||||
volumeSize: number;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red",
|
||||
color: "red"
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
textAlign: "right"
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const,
|
||||
justifyContent: "flex-start" as const
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8,
|
||||
marginLeft: 8
|
||||
},
|
||||
bottomContainer: {
|
||||
display: "flex",
|
||||
@@ -42,39 +43,39 @@ const styles = (theme: Theme) =>
|
||||
alignItems: "center",
|
||||
"& div": {
|
||||
flexGrow: 1,
|
||||
width: "100%",
|
||||
},
|
||||
width: "100%"
|
||||
}
|
||||
},
|
||||
factorElements: {
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
justifyContent: "flex-start"
|
||||
},
|
||||
sizeNumber: {
|
||||
fontSize: 35,
|
||||
fontWeight: 700,
|
||||
textAlign: "center",
|
||||
textAlign: "center"
|
||||
},
|
||||
sizeDescription: {
|
||||
fontSize: 14,
|
||||
color: "#777",
|
||||
textAlign: "center",
|
||||
textAlign: "center"
|
||||
},
|
||||
...modalBasic,
|
||||
...modalBasic
|
||||
});
|
||||
|
||||
const AddZoneModal = ({
|
||||
tenant,
|
||||
classes,
|
||||
open,
|
||||
onCloseZoneAndReload,
|
||||
volumesPerInstance,
|
||||
volumeSize,
|
||||
onCloseZoneAndReload
|
||||
}: IAddZoneProps) => {
|
||||
const [addSending, setAddSending] = useState<boolean>(false);
|
||||
const [zoneName, setZoneName] = useState<string>("");
|
||||
const [numberOfInstances, setNumberOfInstances] = useState<number>(0);
|
||||
const [numberOfNodes, setNumberOfNodes] = useState<number>(0);
|
||||
const [volumeSize, setVolumeSize] = useState<number>(0);
|
||||
const [volumesPerServer, setVolumesPerSever] = useState<number>(0);
|
||||
|
||||
const instanceCapacity: number = volumeSize * volumesPerInstance;
|
||||
const totalCapacity: number = instanceCapacity * numberOfInstances;
|
||||
const instanceCapacity: number = volumeSize * 1073741824 * volumesPerServer;
|
||||
const totalCapacity: number = instanceCapacity * numberOfNodes;
|
||||
|
||||
return (
|
||||
<ModalWrapper
|
||||
@@ -88,30 +89,66 @@ const AddZoneModal = ({
|
||||
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
setAddSending(true);
|
||||
const data: IAddZoneRequest = {
|
||||
name: "",
|
||||
servers: numberOfNodes,
|
||||
volumes_per_server: volumesPerServer,
|
||||
volume_configuration: {
|
||||
size: volumeSize * 1073741824,
|
||||
storage_class: "",
|
||||
labels: null
|
||||
}
|
||||
};
|
||||
api
|
||||
.invoke(
|
||||
"POST",
|
||||
`/api/v1/namespaces/${tenant.namespace}/tenants/${tenant.name}/zones`,
|
||||
data
|
||||
)
|
||||
.then(() => {
|
||||
setAddSending(false);
|
||||
onCloseZoneAndReload(true);
|
||||
})
|
||||
.catch(err => {
|
||||
setAddSending(false);
|
||||
// setDeleteError(err);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
<InputBoxWrapper
|
||||
id="zone_name"
|
||||
name="zone_name"
|
||||
type="string"
|
||||
id="number_of_nodes"
|
||||
name="number_of_nodes"
|
||||
type="number"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setZoneName(e.target.value);
|
||||
setNumberOfNodes(parseInt(e.target.value));
|
||||
}}
|
||||
label="Name"
|
||||
value={zoneName}
|
||||
label="Number o Nodes"
|
||||
value={numberOfNodes.toString(10)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<InputBoxWrapper
|
||||
id="number_instances"
|
||||
name="number_instances"
|
||||
id="zone_size"
|
||||
name="zone_size"
|
||||
type="number"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setNumberOfInstances(parseInt(e.target.value));
|
||||
setVolumeSize(parseInt(e.target.value));
|
||||
}}
|
||||
label="Drives per Server"
|
||||
value={numberOfInstances.toString(10)}
|
||||
label="Volume Size (Gi)"
|
||||
value={volumeSize.toString(10)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<InputBoxWrapper
|
||||
id="volumes_per_sever"
|
||||
name="volumes_per_sever"
|
||||
type="number"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setVolumesPerSever(parseInt(e.target.value));
|
||||
}}
|
||||
label="Volumes per Server"
|
||||
value={volumesPerServer.toString(10)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
|
||||
@@ -42,25 +42,25 @@ interface ITenantDetailsProps {
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red",
|
||||
color: "red"
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
textAlign: "right"
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const,
|
||||
justifyContent: "flex-start" as const
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8,
|
||||
marginLeft: 8
|
||||
},
|
||||
containerHeader: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
justifyContent: "space-between"
|
||||
},
|
||||
paperContainer: {
|
||||
padding: "15px 15px 15px 50px",
|
||||
padding: "15px 15px 15px 50px"
|
||||
},
|
||||
infoGrid: {
|
||||
display: "grid",
|
||||
@@ -68,27 +68,27 @@ const styles = (theme: Theme) =>
|
||||
gridGap: 8,
|
||||
"& div": {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
alignItems: "center"
|
||||
},
|
||||
"& div:nth-child(odd)": {
|
||||
justifyContent: "flex-end",
|
||||
fontWeight: 700,
|
||||
fontWeight: 700
|
||||
},
|
||||
"& div:nth-child(2n)": {
|
||||
paddingRight: 35,
|
||||
},
|
||||
paddingRight: 35
|
||||
}
|
||||
},
|
||||
masterActions: {
|
||||
width: "25%",
|
||||
minWidth: "120px",
|
||||
"& div": {
|
||||
margin: "5px 0px",
|
||||
},
|
||||
margin: "5px 0px"
|
||||
}
|
||||
},
|
||||
actionsTray: {
|
||||
textAlign: "right",
|
||||
textAlign: "right"
|
||||
},
|
||||
...modalBasic,
|
||||
...modalBasic
|
||||
});
|
||||
|
||||
const mainPagination = {
|
||||
@@ -99,9 +99,9 @@ const mainPagination = {
|
||||
page: 0,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
native: true
|
||||
},
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
ActionsComponent: MinTablePaginationActions
|
||||
};
|
||||
|
||||
const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
@@ -142,31 +142,45 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
|
||||
const loadInfo = () => {
|
||||
const tenantName = match.params["tenantName"];
|
||||
const tenantNamespace = match.params["tenantNamespace"];
|
||||
|
||||
setLoading(true);
|
||||
|
||||
api
|
||||
.invoke("GET", `/api/v1/tenants/${tenantName}`)
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}`
|
||||
)
|
||||
.then((res: ITenant) => {
|
||||
const total = res.volume_count * res.volume_size;
|
||||
|
||||
setCapacity(total);
|
||||
setZoneCount(res.zone_count);
|
||||
setVolumes(res.volume_count);
|
||||
setInstances(res.instance_count);
|
||||
const resZones = !res.zones ? [] : res.zones;
|
||||
const total = res.volume_count * res.volume_size;
|
||||
let totalInstances = 0;
|
||||
let totalVolumes = 0;
|
||||
let count = 1;
|
||||
for (let zone of resZones) {
|
||||
zone.volumes = res.volumes_per_server;
|
||||
const cap = res.volumes_per_server * res.volume_size * zone.servers;
|
||||
const cap =
|
||||
zone.volumes_per_server *
|
||||
zone.servers *
|
||||
zone.volume_configuration.size;
|
||||
zone.name = `zone-${count}`;
|
||||
zone.capacity = niceBytes(cap + "");
|
||||
zone.volumes = zone.servers * zone.volumes_per_server;
|
||||
totalInstances += zone.servers;
|
||||
totalVolumes += zone.volumes;
|
||||
count += 1;
|
||||
}
|
||||
setCapacity(res.total_size);
|
||||
setZoneCount(resZones.length);
|
||||
setVolumes(totalVolumes);
|
||||
setInstances(totalInstances);
|
||||
|
||||
setZones(resZones);
|
||||
|
||||
setTenant(res);
|
||||
setError("");
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
setError(err);
|
||||
setLoading(false);
|
||||
});
|
||||
@@ -182,8 +196,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
<AddZoneModal
|
||||
open={addZoneOpen}
|
||||
onCloseZoneAndReload={onCloseZoneAndRefresh}
|
||||
volumeSize={tenant.volume_size}
|
||||
volumesPerInstance={tenant.volumes_per_server}
|
||||
tenant={tenant}
|
||||
/>
|
||||
)}
|
||||
{addBucketOpen && (
|
||||
@@ -212,40 +225,18 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
<div className={classes.infoGrid}>
|
||||
<div>Capacity:</div>
|
||||
<div>{niceBytes(capacity.toString(10))}</div>
|
||||
<div>Minio:</div>
|
||||
<div>{tenant ? tenant.image : ""}</div>
|
||||
<div>Console:</div>
|
||||
<div>{tenant ? tenant.console_image : ""}</div>
|
||||
<div>Zones:</div>
|
||||
<div>{zoneCount}</div>
|
||||
<div>External IDP:</div>
|
||||
<div>
|
||||
{externalIDP ? "Yes" : "No"}
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={() => {}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
<div>Instances:</div>
|
||||
<div>{instances}</div>
|
||||
<div>External KMS:</div>
|
||||
<div>{externalKMS ? "Yes" : "No"} </div>
|
||||
<div>Volumes:</div>
|
||||
<div>{volumes}</div>
|
||||
</div>
|
||||
</Paper>
|
||||
<div className={classes.masterActions}>
|
||||
<div>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
fullWidth
|
||||
onClick={() => {}}
|
||||
>
|
||||
Warp
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<br />
|
||||
@@ -261,185 +252,50 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
aria-label="tenant-tabs"
|
||||
>
|
||||
<Tab label="Zones" />
|
||||
<Tab label="Buckets" />
|
||||
<Tab label="Replication" />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
<Grid item xs={6} className={classes.actionsTray}>
|
||||
{selectedTab === 0 && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<CreateIcon />}
|
||||
onClick={() => {
|
||||
setAddZone(true);
|
||||
}}
|
||||
>
|
||||
Add Zone
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{selectedTab === 1 && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<CreateIcon />}
|
||||
onClick={() => {
|
||||
setAddBucketOpen(true);
|
||||
}}
|
||||
>
|
||||
Create Bucket
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{selectedTab === 2 && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<CreateIcon />}
|
||||
onClick={() => {
|
||||
setAddReplicationOpen(true);
|
||||
}}
|
||||
>
|
||||
Add Replication
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<CreateIcon />}
|
||||
onClick={() => {
|
||||
setAddZone(true);
|
||||
}}
|
||||
>
|
||||
Add Zone
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<br />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{selectedTab === 0 && (
|
||||
<TableWrapper
|
||||
itemActions={[
|
||||
{
|
||||
type: "view",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
<TableWrapper
|
||||
itemActions={[
|
||||
{
|
||||
type: "delete",
|
||||
onClick: element => {
|
||||
console.log(element);
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{ label: "Name", elementKey: "name" },
|
||||
{ label: "Capacity", elementKey: "capacity" },
|
||||
{ label: "# of Instances", elementKey: "servers" },
|
||||
{ label: "# of Drives", elementKey: "volumes" },
|
||||
]}
|
||||
isLoading={false}
|
||||
records={zones}
|
||||
entityName="Zones"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
...mainPagination,
|
||||
onChangePage: () => {},
|
||||
onChangeRowsPerPage: () => {},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedTab === 1 && (
|
||||
<TableWrapper
|
||||
itemActions={[
|
||||
{
|
||||
type: "view",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
},
|
||||
{
|
||||
type: "replicate",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
},
|
||||
{
|
||||
type: "mirror",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{
|
||||
label: "Status",
|
||||
elementKey: "status",
|
||||
},
|
||||
{ label: "Name", elementKey: "name" },
|
||||
{ label: "AccessPolicy", elementKey: "access_policy" },
|
||||
]}
|
||||
isLoading={false}
|
||||
records={[]}
|
||||
entityName="Buckets"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
...mainPagination,
|
||||
onChangePage: () => {},
|
||||
onChangeRowsPerPage: () => {},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedTab === 2 && (
|
||||
<TableWrapper
|
||||
itemActions={[
|
||||
{
|
||||
type: "view",
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{
|
||||
label: "Source",
|
||||
elementKey: "source",
|
||||
},
|
||||
{ label: "Source Bucket", elementKey: "source_bucket" },
|
||||
{ label: "Destination", elementKey: "destination" },
|
||||
{
|
||||
label: "Destination Bucket",
|
||||
elementKey: "destination_bucket",
|
||||
},
|
||||
]}
|
||||
isLoading={false}
|
||||
records={[]}
|
||||
entityName="Replication"
|
||||
idField="id"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: 0,
|
||||
rowsPerPage: 0,
|
||||
page: 0,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: () => {},
|
||||
onChangeRowsPerPage: () => {},
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
sendOnlyId: true
|
||||
}
|
||||
]}
|
||||
columns={[
|
||||
{ label: "Name", elementKey: "name" },
|
||||
{ label: "Capacity", elementKey: "capacity" },
|
||||
{ label: "# of Instances", elementKey: "servers" },
|
||||
{ label: "# of Drives", elementKey: "volumes" }
|
||||
]}
|
||||
isLoading={false}
|
||||
records={zones}
|
||||
entityName="Zones"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
...mainPagination,
|
||||
onChangePage: () => {},
|
||||
onChangeRowsPerPage: () => {}
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -1531,6 +1531,9 @@ func updateTenantZones(
|
||||
// replace zones array
|
||||
minInst.Spec.Zones = newZoneArray
|
||||
|
||||
minInst = minInst.DeepCopy()
|
||||
minInst.EnsureDefaults()
|
||||
|
||||
payloadBytes, err := json.Marshal(minInst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user