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:
@@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IIcon, selected, unSelected } from "./common";
|
import { IIcon, selected, unSelected } from "./common";
|
||||||
|
|
||||||
const PencilIcon = ({ active = false }: IIcon) => {
|
const DescriptionIcon = ({ active = false }: IIcon) => {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -18,4 +18,4 @@ const PencilIcon = ({ active = false }: IIcon) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PencilIcon;
|
export default DescriptionIcon;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
modalBasic,
|
modalBasic,
|
||||||
} from "../../Common/FormComponents/common/styleLibrary";
|
} from "../../Common/FormComponents/common/styleLibrary";
|
||||||
import Grid from "@material-ui/core/Grid";
|
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 Tabs from "@material-ui/core/Tabs";
|
||||||
import Tab from "@material-ui/core/Tab";
|
import Tab from "@material-ui/core/Tab";
|
||||||
import { CreateIcon } from "../../../../icons";
|
import { CreateIcon } from "../../../../icons";
|
||||||
@@ -40,6 +40,9 @@ import Watch from "./Watch/Watch";
|
|||||||
import Heal from "./Heal/Heal";
|
import Heal from "./Heal/Heal";
|
||||||
import PageHeader from "../../Common/PageHeader/PageHeader";
|
import PageHeader from "../../Common/PageHeader/PageHeader";
|
||||||
import UsageBarWrapper from "../../Common/UsageBarWrapper/UsageBarWrapper";
|
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 {
|
interface ITenantDetailsProps {
|
||||||
classes: any;
|
classes: any;
|
||||||
@@ -100,6 +103,18 @@ const styles = (theme: Theme) =>
|
|||||||
actionsTray: {
|
actionsTray: {
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
},
|
},
|
||||||
|
updateButton: {
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
border: 0,
|
||||||
|
padding: "0 6px",
|
||||||
|
cursor: "pointer",
|
||||||
|
"&:focus, &:active": {
|
||||||
|
outline: "none",
|
||||||
|
},
|
||||||
|
"& svg": {
|
||||||
|
height: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
...modalBasic,
|
...modalBasic,
|
||||||
...containerForHeader(theme.spacing(4)),
|
...containerForHeader(theme.spacing(4)),
|
||||||
});
|
});
|
||||||
@@ -119,6 +134,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
|||||||
const [loadingUsage, setLoadingUsage] = useState<boolean>(true);
|
const [loadingUsage, setLoadingUsage] = useState<boolean>(true);
|
||||||
const [usageError, setUsageError] = useState<string>("");
|
const [usageError, setUsageError] = useState<string>("");
|
||||||
const [usage, setUsage] = useState<number>(0);
|
const [usage, setUsage] = useState<number>(0);
|
||||||
|
const [updateMinioVersion, setUpdateMinioVersion] = useState<boolean>(false);
|
||||||
|
|
||||||
const tenantName = match.params["tenantName"];
|
const tenantName = match.params["tenantName"];
|
||||||
const tenantNamespace = match.params["tenantNamespace"];
|
const tenantNamespace = match.params["tenantNamespace"];
|
||||||
@@ -228,6 +244,16 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
|||||||
closeModalAndRefresh={closeReplicationAndRefresh}
|
closeModalAndRefresh={closeReplicationAndRefresh}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{updateMinioVersion && (
|
||||||
|
<UpdateTenantModal
|
||||||
|
open={updateMinioVersion}
|
||||||
|
closeModalAndRefresh={() => {
|
||||||
|
setUpdateMinioVersion(false);
|
||||||
|
}}
|
||||||
|
idTenant={tenantName}
|
||||||
|
namespace={tenantNamespace}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<PageHeader label={`Tenant > ${match.params["tenantName"]}`} />
|
<PageHeader label={`Tenant > ${match.params["tenantName"]}`} />
|
||||||
<Grid item xs={12} className={classes.container} />
|
<Grid item xs={12} className={classes.container} />
|
||||||
<Grid container>
|
<Grid container>
|
||||||
@@ -245,7 +271,17 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
|||||||
<div>Capacity:</div>
|
<div>Capacity:</div>
|
||||||
<div>{niceBytes(capacity.toString(10))}</div>
|
<div>{niceBytes(capacity.toString(10))}</div>
|
||||||
<div>Minio:</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>Clusters:</div>
|
||||||
<div>{poolCount}</div>
|
<div>{poolCount}</div>
|
||||||
<div>Console:</div>
|
<div>Console:</div>
|
||||||
|
|||||||
@@ -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);
|
||||||
Reference in New Issue
Block a user