Added Edit minio image functionality (#474)

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Cesar N <ces.nietor@gmail.com>
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
This commit is contained in:
Alex
2020-12-07 13:27:16 -06:00
committed by GitHub
parent 402e07c844
commit 5bcf245ed9
3 changed files with 292 additions and 4 deletions

View File

@@ -1,7 +1,7 @@
import React from "react";
import { IIcon, selected, unSelected } from "./common";
const PencilIcon = ({ active = false }: IIcon) => {
const DescriptionIcon = ({ active = false }: IIcon) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -18,4 +18,4 @@ const PencilIcon = ({ active = false }: IIcon) => {
);
};
export default PencilIcon;
export default DescriptionIcon;

View File

@@ -22,7 +22,7 @@ import {
modalBasic,
} from "../../Common/FormComponents/common/styleLibrary";
import Grid from "@material-ui/core/Grid";
import { Button } from "@material-ui/core";
import { Button, IconButton } from "@material-ui/core";
import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
import { CreateIcon } from "../../../../icons";
@@ -40,6 +40,9 @@ import Watch from "./Watch/Watch";
import Heal from "./Heal/Heal";
import PageHeader from "../../Common/PageHeader/PageHeader";
import UsageBarWrapper from "../../Common/UsageBarWrapper/UsageBarWrapper";
import UpdateTenantModal from "./UpdateTenantModal";
import EditIcon from "@material-ui/icons/Edit";
import PencilIcon from "../../Common/TableWrapper/TableActionIcons/PencilIcon";
interface ITenantDetailsProps {
classes: any;
@@ -100,6 +103,18 @@ const styles = (theme: Theme) =>
actionsTray: {
textAlign: "right",
},
updateButton: {
backgroundColor: "transparent",
border: 0,
padding: "0 6px",
cursor: "pointer",
"&:focus, &:active": {
outline: "none",
},
"& svg": {
height: 12,
},
},
...modalBasic,
...containerForHeader(theme.spacing(4)),
});
@@ -119,6 +134,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
const [loadingUsage, setLoadingUsage] = useState<boolean>(true);
const [usageError, setUsageError] = useState<string>("");
const [usage, setUsage] = useState<number>(0);
const [updateMinioVersion, setUpdateMinioVersion] = useState<boolean>(false);
const tenantName = match.params["tenantName"];
const tenantNamespace = match.params["tenantNamespace"];
@@ -228,6 +244,16 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
closeModalAndRefresh={closeReplicationAndRefresh}
/>
)}
{updateMinioVersion && (
<UpdateTenantModal
open={updateMinioVersion}
closeModalAndRefresh={() => {
setUpdateMinioVersion(false);
}}
idTenant={tenantName}
namespace={tenantNamespace}
/>
)}
<PageHeader label={`Tenant > ${match.params["tenantName"]}`} />
<Grid item xs={12} className={classes.container} />
<Grid container>
@@ -245,7 +271,17 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
<div>Capacity:</div>
<div>{niceBytes(capacity.toString(10))}</div>
<div>Minio:</div>
<div>{tenant ? tenant.image : ""}</div>
<div>
{tenant ? tenant.image : ""}{" "}
<button
className={classes.updateButton}
onClick={() => {
setUpdateMinioVersion(true);
}}
>
<PencilIcon active={false} />
</button>
</div>
<div>Clusters:</div>
<div>{poolCount}</div>
<div>Console:</div>

View File

@@ -0,0 +1,252 @@
import React, { useState, Fragment, useEffect } from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import { Button, Grid } from "@material-ui/core";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import api from "../../../../common/api";
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
interface IUpdateTenantModal {
open: boolean;
closeModalAndRefresh: (update: boolean) => any;
namespace: string;
idTenant: string;
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red",
},
buttonContainer: {
textAlign: "right",
},
...modalBasic,
});
const UpdateTenantModal = ({
open,
closeModalAndRefresh,
namespace,
idTenant,
classes,
}: IUpdateTenantModal) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isSending, setIsSending] = useState<boolean>(false);
const [error, setError] = useState<string>("");
const [minioImage, setMinioImage] = useState<string>("");
const [consoleImage, setConsoleImage] = useState<string>("");
const [imageRegistry, setImageRegistry] = useState<boolean>(false);
const [imageRegistryEndpoint, setImageRegistryEndpoint] = useState<string>(
""
);
const [imageRegistryUsername, setImageRegistryUsername] = useState<string>(
""
);
const [imageRegistryPassword, setImageRegistryPassword] = useState<string>(
""
);
const [validMinioImage, setValidMinioImage] = useState<boolean>(true);
const [validConsoleImage, setValidConsoleImage] = useState<boolean>(true);
useEffect(() => {
validateImage("minioImage");
}, [minioImage]);
useEffect(() => {
validateImage("consoleImage");
}, [consoleImage]);
const closeAction = () => {
closeModalAndRefresh(false);
};
const resetForm = () => {
setMinioImage("");
setConsoleImage("");
setImageRegistry(false);
setImageRegistryEndpoint("");
setImageRegistryUsername("");
setImageRegistryPassword("");
};
const updateMinIOImage = () => {
setIsSending(true);
let payload = {
image: minioImage,
console_image: consoleImage,
enable_prometheus: true,
};
if (imageRegistry) {
const registry: any = {
image_registry: {
registry: imageRegistryEndpoint,
username: imageRegistryUsername,
password: imageRegistryPassword,
},
};
payload = {
...payload,
...registry,
};
}
api
.invoke(
"PUT",
`/api/v1/namespaces/${namespace}/tenants/${idTenant}`,
payload
)
.then((res) => {
setIsSending(false);
closeModalAndRefresh(true);
})
.catch((error) => {
setError(error);
setIsSending(false);
});
};
const validateImage = (fieldToCheck: string) => {
const pattern = new RegExp("^$|^((.*?)/(.*?):(.+))$");
switch (fieldToCheck) {
case "consoleImage":
setValidConsoleImage(pattern.test(consoleImage));
break;
case "minioImage":
setValidMinioImage(pattern.test(minioImage));
break;
}
};
return (
<ModalWrapper
title={"Update MinIO Version"}
modalOpen={open}
onClose={closeAction}
>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
{error !== "" && <span className={classes.errorBlock}>{error}</span>}
<span>
Please enter the MinIO image from dockerhub to use. If blank, then
latest build will be used.
</span>
<br />
<br />
<Grid item xs={12}>
<InputBoxWrapper
value={minioImage}
label={"MinIO's Image"}
id={"minioImage"}
name={"minioImage"}
placeholder={"E.g. minio/minio:RELEASE.2020-05-08T02-40-49Z"}
onChange={(e) => {
setMinioImage(e.target.value);
}}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
value={consoleImage}
label={"Console's Image"}
id={"consoleImage"}
name={"consoleImage"}
placeholder={"E.g. minio/console:v0.3.13"}
onChange={(e) => {
setConsoleImage(e.target.value);
}}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="imageRegistry"
id="setImageRegistry"
name="setImageRegistry"
checked={imageRegistry}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setImageRegistry(!imageRegistry);
}}
label={"Set Custom Image Registry"}
indicatorLabels={["Yes", "No"]}
/>
</Grid>
{imageRegistry && (
<Fragment>
<Grid item xs={12}>
<InputBoxWrapper
value={imageRegistryEndpoint}
label={"Endpoint"}
id={"imageRegistry"}
name={"imageRegistry"}
placeholder={"E.g. https://index.docker.io/v1/"}
onChange={(e) => {
setImageRegistryEndpoint(e.target.value);
}}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
value={imageRegistryUsername}
label={"Username"}
id={"imageRegistryUsername"}
name={"imageRegistryUsername"}
placeholder={"Enter image registry username"}
onChange={(e) => {
setImageRegistryUsername(e.target.value);
}}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
value={imageRegistryPassword}
label={"Password"}
id={"imageRegistryPassword"}
name={"imageRegistryPassword"}
placeholder={"Enter image registry password"}
onChange={(e) => {
setImageRegistryPassword(e.target.value);
}}
/>
</Grid>
</Fragment>
)}
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
<button
type="button"
color="primary"
className={classes.clearButton}
onClick={resetForm}
>
Clear
</button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={
!validMinioImage ||
!validConsoleImage ||
(imageRegistry &&
(imageRegistryEndpoint.trim() === "" ||
imageRegistryUsername.trim() === "" ||
imageRegistryPassword.trim() === "")) ||
isSending
}
onClick={updateMinIOImage}
>
Save
</Button>
</Grid>
</Grid>
</ModalWrapper>
);
};
export default withStyles(styles)(UpdateTenantModal);