UX Create New Tenant (#1266)

This commit is contained in:
Prakash Senthil Vel
2021-11-30 19:21:55 +00:00
committed by GitHub
parent eefc6a7894
commit 9db0c358a4
15 changed files with 1336 additions and 811 deletions

View File

@@ -125,7 +125,7 @@ export const RadioGroupSelector = ({
)}
</InputLabel>
</Grid>
<Grid item xs>
<Grid item xs className={classes.radioOptionsLayout}>
<RadioGroup
aria-label={id}
id={id}

View File

@@ -732,6 +732,7 @@ export const wizardCommon = {
},
h3Section: {
marginTop: 0,
margin: 0,
},
descriptionText: {
fontSize: 13,
@@ -751,6 +752,7 @@ export const wizardCommon = {
},
paperWrapper: {
padding: 12,
border: 0,
},
};
@@ -874,6 +876,9 @@ export const inputFieldStyles = {
borderColor: "#07193E",
borderWidth: 1,
},
"&.Mui-error + p": {
marginLeft: 3,
},
},
disabled: {
"&.MuiOutlinedInput-root::before": {
@@ -1202,3 +1207,10 @@ export const advancedFilterToggleStyles: any = {
transform: "rotateZ(90deg)",
},
};
export const createTenantCommon: any = {
fieldGroup: {
border: "1px solid #EAEAEA",
paddingTop: 5,
},
};

View File

@@ -69,6 +69,7 @@ const styles = (theme: Theme) =>
paddedContentGrid: {
marginTop: 8,
padding: "0 10px",
minHeight: 400,
},
stepsLabel: {
fontSize: 20,
@@ -89,6 +90,21 @@ const styles = (theme: Theme) =>
width: "100%",
maxHeight: 90,
},
verticalSteps: {
borderRight: "1px solid #EAEAEA",
background: "#FBFAFA",
},
stepsContainer: {
paddingTop: 0,
"& .MuiButtonBase-root.Mui-selected": {
background: "#EAEAEA",
},
},
stepItem: {
"&:hover": {
background: "rgba(247,247,247,0.7)",
},
},
});
const GenericWizard = ({
@@ -143,14 +159,24 @@ const GenericWizard = ({
const stepsList = () => {
return (
<Fragment>
<List component="nav" dense={true}>
<List
component="nav"
dense={true}
classes={{
root: classes.stepsContainer,
}}
>
{wizardSteps.map((step, index) => {
return (
<ListItem
button
disableRipple
onClick={() => pageChange(index)}
key={`wizard-${index.toString()}`}
selected={currentStep === index}
classes={{
root: classes.stepItem,
}}
>
<ListItemText primary={step.label} />
</ListItem>
@@ -194,7 +220,15 @@ const GenericWizard = ({
</Fragment>
) : (
<Fragment>
<Grid item xs={12} sm={2} md={2} lg={2} xl={2}>
<Grid
item
xs={12}
sm={2}
md={2}
lg={2}
xl={2}
className={classes.verticalSteps}
>
{stepsList()}
</Grid>
</Fragment>

View File

@@ -26,12 +26,14 @@ const styles = (theme: Theme) =>
wizardStepContainer: {
display: "flex",
flexDirection: "column",
flex: 1,
},
wizardComponent: {
overflowY: "auto",
marginBottom: 10,
height: "calc(100vh - 100px - 80px)",
maxWidth: 840,
minHeight: 400,
flex: 1,
width: "100%",
},
wizardModal: {
@@ -53,9 +55,9 @@ const styles = (theme: Theme) =>
},
},
buttonInnerContainer: {
maxWidth: 840,
width: "100%",
textAlign: "right" as const,
marginRight: 15,
},
});

View File

@@ -51,6 +51,8 @@ import Affinity from "./Steps/Affinity";
import PageHeader from "../../Common/PageHeader/PageHeader";
import history from "../../../../history";
import Images from "./Steps/Images";
import PageLayout from "../../Common/Layout/PageLayout";
import BackLink from "../../../../common/BackLink";
interface IAddTenantProps {
setErrorSnackMessage: typeof setErrorSnackMessage;
@@ -69,6 +71,9 @@ const styles = (theme: Theme) =>
buttonContainer: {
textAlign: "right",
},
pageBox: {
border: "1px solid #EAEAEA",
},
...modalBasic,
...wizardCommon,
...settingsCommon,
@@ -728,16 +733,17 @@ const AddTenant = ({
/>
)}
<PageHeader label={"Create New Tenant"} />
<Grid container>
<BackLink to={"/tenants"} label={"Return to Tenant List"} />
<PageLayout>
{addSending && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
<Grid item xs={12}>
<Grid item xs={12} className={classes.pageBox}>
<GenericWizard wizardSteps={filteredWizardSteps} />
</Grid>
</Grid>
</PageLayout>
</Fragment>
);
};

View File

@@ -56,12 +56,62 @@ const styles = (theme: Theme) =>
textAlign: "right",
},
overlayAction: {
lineHeight: "50px",
float: "left",
marginLeft: 10,
"& svg": {
maxWidth: 15,
maxHeight: 15,
},
"& button": {
background: "#EAEAEA",
},
},
radioOptionsLayout: {
"& div": {
display: "flex",
flexFlow: "column",
},
},
affinityConfigField: {
display: "flex",
},
affinityFieldLabel: {
display: "flex",
flexFlow: "column",
flex: 1,
},
radioField: {
display: "flex",
alignItems: "flex-start",
marginTop: 10,
"& div:first-child": {
display: "flex",
flexFlow: "column",
alignItems: "baseline",
textAlign: "left !important",
},
},
affinityLabelKey: {
"& div:first-child": {
marginBottom: 0,
},
},
affinityLabelValue: {
marginLeft: 10,
"& div:first-child": {
marginBottom: 0,
},
},
rowActions: {
display: "flex",
alignItems: "center",
},
fieldContainer: {
marginBottom: 0,
},
affinityRow: {
marginBottom: 10,
display: "flex",
},
...modalBasic,
...wizardCommon,
@@ -196,22 +246,32 @@ const Affinity = ({
Configure how pods will be assigned to nodes
</span>
</div>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={podAffinity}
id="affinity-options"
name="affinity-options"
label="Type"
onChange={(e) => {
updateField("podAffinity", e.target.value);
}}
selectorOptions={[
{ label: "None", value: "none" },
{ label: "Default (Pod Anti-Affinnity)", value: "default" },
{ label: "Node Selector", value: "nodeSelector" },
]}
/>
MinIO supports multiple configurations for Pod Affinity
<Grid xs={12} className={classes.affinityConfigField}>
<Grid item className={classes.affinityFieldLabel}>
<div className={classes.label}>Type</div>
<div
className={`${classes.descriptionText} ${classes.affinityHelpText}`}
>
MinIO supports multiple configurations for Pod Affinity
</div>
<Grid item className={classes.radioField}>
<RadioGroupSelector
classes={classes}
currentSelection={podAffinity}
id="affinity-options"
name="affinity-options"
label={" "}
onChange={(e) => {
updateField("podAffinity", e.target.value);
}}
selectorOptions={[
{ label: "None", value: "none" },
{ label: "Default (Pod Anti-Affinnity)", value: "default" },
{ label: "Node Selector", value: "nodeSelector" },
]}
/>
</Grid>
</Grid>
</Grid>
{podAffinity === "nodeSelector" && (
<Fragment>
@@ -238,8 +298,8 @@ const Affinity = ({
{keyValuePairs &&
keyValuePairs.map((kvp, i) => {
return (
<React.Fragment>
<Grid item xs={5}>
<Grid item xs={12} className={classes.affinityRow}>
<Grid item xs={5} className={classes.affinityLabelKey}>
{keyOptions.length > 0 && (
<SelectWrapper
onChange={(e: SelectChangeEvent<string>) => {
@@ -258,6 +318,7 @@ const Affinity = ({
label={""}
value={kvp.key}
options={keyOptions}
classes={classes.fieldContainer}
/>
)}
{keyOptions.length === 0 && (
@@ -276,10 +337,11 @@ const Affinity = ({
}}
index={i}
placeholder={"Key"}
classes={classes.fieldContainer}
/>
)}
</Grid>
<Grid item xs={5}>
<Grid item xs={5} className={classes.affinityLabelValue}>
{keyOptions.length > 0 && (
<SelectWrapper
onChange={(e: SelectChangeEvent<string>) => {
@@ -301,6 +363,7 @@ const Affinity = ({
})
: []
}
classes={classes.fieldContainer}
/>
)}
{keyOptions.length === 0 && (
@@ -319,10 +382,11 @@ const Affinity = ({
}}
index={i}
placeholder={"value"}
classes={classes.fieldContainer}
/>
)}
</Grid>
<Grid item xs={2}>
<Grid item xs={2} className={classes.rowActions}>
<div className={classes.overlayAction}>
<IconButton
size={"small"}
@@ -359,7 +423,7 @@ const Affinity = ({
</div>
)}
</Grid>
</React.Fragment>
</Grid>
);
})}
</Grid>

View File

@@ -14,13 +14,14 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useCallback, useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { connect } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Grid, Paper, SelectChangeEvent } from "@mui/material";
import {
createTenantCommon,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -77,6 +78,62 @@ const styles = (theme: Theme) =>
buttonContainer: {
textAlign: "right",
},
configSectionItem: {
marginRight: 15,
"& .multiContainer": {
border: "1px solid red",
},
},
inputLabel: {
fontWeight: 300,
fontSize: 14,
},
textBoxContainer: {
"& input": {
fontWeight: 400,
},
},
tenantCustomizationFields: {
marginLeft: 30, // 2nd Level(15+15)
width: "88%",
margin: "auto",
},
containerItem: {
marginRight: 15,
},
fieldGroup: {
...createTenantCommon.fieldGroup,
paddingTop: 15,
marginBottom: 25,
},
responsiveSectionItem: {
"@media (max-width: 900px)": {
flexFlow: "column",
alignItems: "flex-start",
"& div > div": {
marginBottom: 5,
marginRight: 0,
},
},
},
logSearchCustomFields: {
marginLeft: 20, // 2nd Level(15+15)
padding: 10,
width: "90%",
margin: "auto",
},
fieldSpaceTop: {
marginTop: 15,
},
prometheusCustomFields: {
marginLeft: 20, // 2nd Level(15+15)
padding: 10,
width: "90%",
margin: "auto",
},
...modalBasic,
...wizardCommon,
});
@@ -447,12 +504,13 @@ const Configure = ({
Whether the tenant's services should request an external IP.
</span>
</div>
<Grid item xs={12}>
<Grid item xs={12} className={classes.configSectionItem}>
<FormSwitchWrapper
value="expose_minio"
id="expose_minio"
name="expose_minio"
checked={exposeMinIO}
classes={classes}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
@@ -462,11 +520,12 @@ const Configure = ({
label={"Expose MiniO Service"}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.configSectionItem}>
<FormSwitchWrapper
value="expose_console"
id="expose_console"
name="expose_console"
classes={classes}
checked={exposeConsole}
onChange={(e) => {
const targetD = e.target;
@@ -485,7 +544,7 @@ const Configure = ({
Search, Prometheus add-ons and your Tenant
</span>
</div>
<Grid item xs={12}>
<Grid item xs={12} className={classes.configSectionItem}>
<FormSwitchWrapper
value="tenantConfig"
id="tenant_configuration"
@@ -501,102 +560,109 @@ const Configure = ({
/>
</Grid>
{tenantCustom && (
<Fragment>
<span className={classes.descriptionText}>
SecurityContext for MinIO
</span>
<br />
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="tenant_securityContext_runAsUser"
name="tenant_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
<Grid item xs={12} className={classes.tenantCustomizationFields}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
SecurityContext for MinIO
</legend>
<Grid item xs={12} className={`${classes.configSectionItem}`}>
<div
className={`${classes.multiContainer} ${classes.responsiveSectionItem}`}
>
<div className={classes.containerItem}>
<InputBoxWrapper
type="number"
classes={classes}
id="tenant_securityContext_runAsUser"
name="tenant_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsUser: e.target.value,
});
cleanValidation("tenant_securityContext_runAsUser");
}}
label="Run As User"
value={tenantSecurityContext.runAsUser}
required
error={
validationErrors["tenant_securityContext_runAsUser"] || ""
}
min="0"
/>
</div>
<div className={classes.containerItem}>
<InputBoxWrapper
type="number"
classes={classes}
id="tenant_securityContext_runAsGroup"
name="tenant_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("tenant_securityContext_runAsGroup");
}}
label="Run As Group"
value={tenantSecurityContext.runAsGroup}
required
error={
validationErrors["tenant_securityContext_runAsGroup"] ||
""
}
min="0"
/>
</div>
<div className={classes.containerItem}>
<InputBoxWrapper
type="number"
classes={classes}
id="tenant_securityContext_fsGroup"
name="tenant_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("tenant_securityContext_fsGroup");
}}
label="FsGroup"
value={tenantSecurityContext.fsGroup}
required
error={
validationErrors["tenant_securityContext_fsGroup"] || ""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12} className={classes.configSectionItem}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
classes={classes}
value="tenantSecurityContextRunAsNonRoot"
id="tenant_securityContext_runAsNonRoot"
name="tenant_securityContext_runAsNonRoot"
checked={tenantSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsUser: e.target.value,
runAsNonRoot: checked,
});
cleanValidation("tenant_securityContext_runAsUser");
}}
label="Run As User"
value={tenantSecurityContext.runAsUser}
required
error={
validationErrors["tenant_securityContext_runAsUser"] || ""
}
min="0"
label={"Do not run as Root"}
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="tenant_securityContext_runAsGroup"
name="tenant_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("tenant_securityContext_runAsGroup");
}}
label="Run As Group"
value={tenantSecurityContext.runAsGroup}
required
error={
validationErrors["tenant_securityContext_runAsGroup"] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="tenant_securityContext_fsGroup"
name="tenant_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("tenant_securityContext_fsGroup");
}}
label="FsGroup"
value={tenantSecurityContext.fsGroup}
required
error={
validationErrors["tenant_securityContext_fsGroup"] || ""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
value="tenantSecurityContextRunAsNonRoot"
id="tenant_securityContext_runAsNonRoot"
name="tenant_securityContext_runAsNonRoot"
checked={tenantSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsNonRoot: checked,
});
}}
label={"Do not run as Root"}
/>
</div>
</Grid>
</Fragment>
</Grid>
</fieldset>
</Grid>
)}
<Grid item xs={12}>
<Grid item xs={12} className={classes.configSectionItem}>
<FormSwitchWrapper
value="logSearchConfig"
id="log_search_configuration"
@@ -612,9 +678,10 @@ const Configure = ({
/>
</Grid>
{logSearchCustom && (
<Fragment>
<Grid xs={12} className={classes.logSearchCustomFields}>
<Grid item xs={12}>
<SelectWrapper
classes={classes}
id="log_search_storage_class"
name="log_search_storage_class"
onChange={(e: SelectChangeEvent<string>) => {
@@ -631,37 +698,41 @@ const Configure = ({
</Grid>
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="log_search_volume_size"
name="log_search_volume_size"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchVolumeSize", e.target.value);
cleanValidation("log_search_volume_size");
}}
label="Storage Size [Gi]"
value={logSearchVolumeSize}
required
error={validationErrors["log_search_volume_size"] || ""}
min="0"
/>
</div>
<InputBoxWrapper
type="number"
id="log_search_volume_size"
name="log_search_volume_size"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchVolumeSize", e.target.value);
cleanValidation("log_search_volume_size");
}}
label="Storage Size [Gi]"
value={logSearchVolumeSize}
required
error={validationErrors["log_search_volume_size"] || ""}
min="0"
/>
</div>
</Grid>
<Fragment>
<span className={classes.descriptionText}>
<fieldset
className={`${classes.fieldGroup} ${classes.fieldSpaceTop}`}
>
<legend className={classes.descriptionText}>
SecurityContext for LogSearch
</span>
<br />
<br />
</legend>
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<div
className={`${classes.multiContainer} ${classes.responsiveSectionItem}`}
>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="logSearch_securityContext_runAsUser"
name="logSearch_securityContext_runAsUser"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
@@ -679,11 +750,12 @@ const Configure = ({
min="0"
/>
</div>
<div>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="logSearch_securityContext_runAsGroup"
name="logSearch_securityContext_runAsGroup"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
@@ -702,11 +774,12 @@ const Configure = ({
min="0"
/>
</div>
<div>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="logSearch_securityContext_fsGroup"
name="logSearch_securityContext_fsGroup"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
@@ -733,6 +806,7 @@ const Configure = ({
value="logSearchSecurityContextRunAsNonRoot"
id="logSearch_securityContext_runAsNonRoot"
name="logSearch_securityContext_runAsNonRoot"
classes={classes}
checked={logSearchSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
@@ -746,20 +820,22 @@ const Configure = ({
/>
</div>
</Grid>
</Fragment>
<Fragment>
<span className={classes.descriptionText}>
</fieldset>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
SecurityContext for PostgreSQL
</span>
<br />
<br />
</legend>
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<div
className={`${classes.multiContainer} ${classes.responsiveSectionItem}`}
>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="postgres_securityContext_runAsUser"
name="postgres_securityContext_runAsUser"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
@@ -777,11 +853,12 @@ const Configure = ({
min="0"
/>
</div>
<div>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="postgres_securityContext_runAsGroup"
name="postgres_securityContext_runAsGroup"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
@@ -799,11 +876,12 @@ const Configure = ({
min="0"
/>
</div>
<div>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="postgres_securityContext_fsGroup"
name="postgres_securityContext_fsGroup"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
@@ -829,6 +907,7 @@ const Configure = ({
value="postgresSecurityContextRunAsNonRoot"
id="postgres_securityContext_runAsNonRoot"
name="postgres_securityContext_runAsNonRoot"
classes={classes}
checked={logSearchPostgresSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
@@ -842,10 +921,10 @@ const Configure = ({
/>
</div>
</Grid>
</Fragment>
</Fragment>
</fieldset>
</Grid>
)}
<Grid item xs={12}>
<Grid item xs={12} className={classes.configSectionItem}>
<FormSwitchWrapper
value="prometheusConfig"
id="prometheus_configuration"
@@ -861,11 +940,12 @@ const Configure = ({
/>
</Grid>
{prometheusCustom && (
<Fragment>
<Grid xs={12} className={classes.prometheusCustomFields}>
<Grid item xs={12}>
<SelectWrapper
id="prometheus_storage_class"
name="prometheus_storage_class"
classes={classes}
onChange={(e: SelectChangeEvent<string>) => {
updateField(
"prometheusSelectedStorageClass",
@@ -880,37 +960,39 @@ const Configure = ({
</Grid>
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="prometheus_volume_size"
name="prometheus_volume_size"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusVolumeSize", e.target.value);
cleanValidation("prometheus_volume_size");
}}
label="Storage Size [Gi]"
value={prometheusVolumeSize}
required
error={validationErrors["prometheus_volume_size"] || ""}
min="0"
/>
</div>
<InputBoxWrapper
type="number"
id="prometheus_volume_size"
name="prometheus_volume_size"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusVolumeSize", e.target.value);
cleanValidation("prometheus_volume_size");
}}
label="Storage Size [Gi]"
value={prometheusVolumeSize}
required
error={validationErrors["prometheus_volume_size"] || ""}
min="0"
/>
</div>
</Grid>
<Fragment>
<span className={classes.descriptionText}>
<fieldset
className={`${classes.fieldGroup} ${classes.fieldSpaceTop}`}
>
<legend className={classes.descriptionText}>
SecurityContext for Prometheus
</span>
<br />
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
</legend>
<Grid item xs={12} className={classes.configSectionItem}>
<div
className={`${classes.multiContainer} ${classes.responsiveSectionItem}`}
>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="prometheus_securityContext_runAsUser"
name="prometheus_securityContext_runAsUser"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
@@ -929,11 +1011,12 @@ const Configure = ({
min="0"
/>
</div>
<div>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="prometheus_securityContext_runAsGroup"
name="prometheus_securityContext_runAsGroup"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
@@ -952,11 +1035,12 @@ const Configure = ({
min="0"
/>
</div>
<div>
<div className={classes.configSectionItem}>
<InputBoxWrapper
type="number"
id="prometheus_securityContext_fsGroup"
name="prometheus_securityContext_fsGroup"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
@@ -976,13 +1060,15 @@ const Configure = ({
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<Grid item xs={12} className={classes.configSectionItem}>
<div
className={`${classes.multiContainer} ${classes.fieldSpaceTop}`}
>
<FormSwitchWrapper
value="prometheusSecurityContextRunAsNonRoot"
id="prometheus_securityContext_runAsNonRoot"
name="prometheus_securityContext_runAsNonRoot"
classes={classes}
checked={prometheusSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
@@ -996,8 +1082,8 @@ const Configure = ({
/>
</div>
</Grid>
</Fragment>
</Fragment>
</fieldset>
</Grid>
)}
</Paper>
);

View File

@@ -19,7 +19,7 @@ import { connect } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Paper, Typography } from "@mui/material";
import { Paper } from "@mui/material";
import Grid from "@mui/material/Grid";
import {
updateAddField,
@@ -31,6 +31,8 @@ import {
addFileGemaltoCa,
} from "../../actions";
import {
createTenantCommon,
formFieldStyles,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -106,6 +108,35 @@ const styles = (theme: Theme) =>
buttonContainer: {
textAlign: "right",
},
encryptionTypeOptions: {
marginBottom: 15,
},
mutualTlsConfig: {
marginTop: 15,
"& fieldset": {
flex: 1,
},
},
fileInputField: {
borderBottom: "1px solid #EAEAEA",
"&:last-child": {
borderBottom: 0,
},
"& input": {
borderBottom: 0,
},
},
rightSpacer: {
marginRight: 15,
},
responsiveContainer: {
"@media (max-width: 900px)": {
display: "flex",
flexFlow: "column",
},
},
...createTenantCommon,
...formFieldStyles,
...modalBasic,
...wizardCommon,
});
@@ -443,7 +474,7 @@ const Encryption = ({
</Grid>
{enableEncryption && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.encryptionTypeOptions}>
<RadioGroupSelector
currentSelection={encryptionType}
id="encryptionType"
@@ -481,84 +512,80 @@ const Encryption = ({
</Grid>
{(enableCustomCertsForKES || !enableAutoCert) && (
<Fragment>
<Grid item xs={12}>
<Typography variant="overline" display="block" gutterBottom>
Encryption Service Certificates
</Typography>
</Grid>
<Grid container>
<Grid item xs={6}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileServerCert("key", fileName, encodedValue);
cleanValidation("serverKey");
}}
accept=".key,.pem"
id="serverKey"
name="serverKey"
label="Key"
error={validationErrors["serverKey"] || ""}
value={serverCertificate.key}
required={!enableAutoCert}
/>
</Grid>
<Grid item xs={6}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileServerCert("cert", fileName, encodedValue);
cleanValidation("serverCert");
}}
accept=".cer,.crt,.cert,.pem"
id="serverCert"
name="serverCert"
label="Cert"
error={validationErrors["serverCert"] || ""}
value={serverCertificate.cert}
required={!enableAutoCert}
/>
<Grid item xs={12} style={{ marginBottom: 15 }}>
<fieldset className={classes.fieldGroup}>
<legend>Encryption Service Certificates</legend>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileServerCert("key", fileName, encodedValue);
cleanValidation("serverKey");
}}
accept=".key,.pem"
id="serverKey"
name="serverKey"
label="Key"
error={validationErrors["serverKey"] || ""}
value={serverCertificate.key}
required={!enableAutoCert}
/>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileServerCert("cert", fileName, encodedValue);
cleanValidation("serverCert");
}}
accept=".cer,.crt,.cert,.pem"
id="serverCert"
name="serverCert"
label="Cert"
error={validationErrors["serverCert"] || ""}
value={serverCertificate.cert}
required={!enableAutoCert}
/>
</fieldset>
</Grid>
</Grid>
<Grid item xs={12}>
<Typography variant="overline" display="block" gutterBottom>
Mutual TLS authentication
</Typography>
</Grid>
<Grid container>
<Grid item xs={6}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileClientCert("key", fileName, encodedValue);
cleanValidation("clientKey");
}}
accept=".key,.pem"
id="clientKey"
name="clientKey"
label="Key"
error={validationErrors["clientKey"] || ""}
value={clientCertificate.key}
required={!enableAutoCert}
/>
</Grid>
<Grid item xs={6}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileClientCert("cert", fileName, encodedValue);
cleanValidation("clientCert");
}}
accept=".cer,.crt,.cert,.pem"
id="clientCert"
name="clientCert"
label="Cert"
error={validationErrors["clientCert"] || ""}
value={clientCertificate.cert}
required={!enableAutoCert}
/>
<Grid container style={{ marginBottom: 15 }}>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend>Mutual TLS authentication</legend>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileClientCert("key", fileName, encodedValue);
cleanValidation("clientKey");
}}
accept=".key,.pem"
id="clientKey"
name="clientKey"
label="Key"
error={validationErrors["clientKey"] || ""}
value={clientCertificate.key}
required={!enableAutoCert}
/>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileClientCert("cert", fileName, encodedValue);
cleanValidation("clientCert");
}}
accept=".cer,.crt,.cert,.pem"
id="clientCert"
name="clientCert"
label="Cert"
error={validationErrors["clientCert"] || ""}
value={clientCertificate.cert}
required={!enableAutoCert}
/>
</fieldset>
</Grid>
</Grid>
</Fragment>
)}
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_endpoint"
name="vault_endpoint"
@@ -572,7 +599,7 @@ const Encryption = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_engine"
name="vault_engine"
@@ -584,7 +611,7 @@ const Encryption = ({
value={vaultEngine}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_namespace"
name="vault_namespace"
@@ -595,7 +622,7 @@ const Encryption = ({
value={vaultNamespace}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_prefix"
name="vault_prefix"
@@ -606,65 +633,72 @@ const Encryption = ({
value={vaultPrefix}
/>
</Grid>
<h5>App Role</h5>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_approle_engine"
name="vault_approle_engine"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultAppRoleEngine", e.target.value);
}}
label="Engine"
value={vaultAppRoleEngine}
/>
<fieldset className={classes.fieldGroup}>
<legend>App Role</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_approle_engine"
name="vault_approle_engine"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultAppRoleEngine", e.target.value);
}}
label="Engine"
value={vaultAppRoleEngine}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_id"
name="vault_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultId", e.target.value);
cleanValidation("vault_id");
}}
label="AppRole ID"
value={vaultId}
error={validationErrors["vault_id"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="vault_secret"
name="vault_secret"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultSecret", e.target.value);
cleanValidation("vault_secret");
}}
label="AppRole Secret"
value={vaultSecret}
error={validationErrors["vault_secret"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type="number"
min="0"
id="vault_retry"
name="vault_retry"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultRetry", e.target.value);
cleanValidation("vault_retry");
}}
label="Retry (Seconds)"
value={vaultRetry}
error={validationErrors["vault_retry"] || ""}
/>
</Grid>
</fieldset>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_id"
name="vault_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultId", e.target.value);
cleanValidation("vault_id");
}}
label="AppRole ID"
value={vaultId}
error={validationErrors["vault_id"] || ""}
required
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_secret"
name="vault_secret"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultSecret", e.target.value);
cleanValidation("vault_secret");
}}
label="AppRole Secret"
value={vaultSecret}
error={validationErrors["vault_secret"] || ""}
required
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="0"
id="vault_retry"
name="vault_retry"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultRetry", e.target.value);
cleanValidation("vault_retry");
}}
label="Retry (Seconds)"
value={vaultRetry}
error={validationErrors["vault_retry"] || ""}
/>
</Grid>
<h5>Mutual TLS authentication (optional)</h5>
<Grid container>
<Grid item xs={6}>
<Grid container className={classes.mutualTlsConfig}>
<fieldset className={classes.fieldGroup}>
<legend>Mutual TLS authentication (optional)</legend>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileVaultCert("key", fileName, encodedValue);
cleanValidation("vault_key");
@@ -675,9 +709,8 @@ const Encryption = ({
label="Key"
value={vaultCertificate.key}
/>
</Grid>
<Grid item xs={6}>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileVaultCert("cert", fileName, encodedValue);
cleanValidation("vault_cert");
@@ -688,42 +721,48 @@ const Encryption = ({
label="Cert"
value={vaultCertificate.cert}
/>
</Grid>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileVaultCa(fileName, encodedValue);
cleanValidation("vault_ca");
}}
accept=".cer,.crt,.cert,.pem"
id="vault_ca"
name="vault_ca"
label="CA"
value={vaultCA.cert}
/>
</fieldset>
</Grid>
<Grid item xs={12}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileVaultCa(fileName, encodedValue);
cleanValidation("vault_ca");
}}
accept=".cer,.crt,.cert,.pem"
id="vault_ca"
name="vault_ca"
label="CA"
value={vaultCA.cert}
/>
</Grid>
<h5>Status</h5>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="0"
id="vault_ping"
name="vault_ping"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultPing", e.target.value);
cleanValidation("vault_ping");
}}
label="Ping (Seconds)"
value={vaultPing}
error={validationErrors["vault_ping"] || ""}
/>
<Grid
item
xs={12}
className={classes.formFieldRow}
style={{ marginTop: 15 }}
>
<fieldset className={classes.fieldGroup}>
<legend>Status</legend>
<InputBoxWrapper
type="number"
min="0"
id="vault_ping"
name="vault_ping"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("vaultPing", e.target.value);
cleanValidation("vault_ping");
}}
label="Ping (Seconds)"
value={vaultPing}
error={validationErrors["vault_ping"] || ""}
/>
</fieldset>
</Grid>
</Fragment>
)}
{encryptionType === "azure" && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="azure_endpoint"
name="azure_endpoint"
@@ -736,51 +775,55 @@ const Encryption = ({
error={validationErrors["azure_endpoint"] || ""}
/>
</Grid>
<h5>Credentials</h5>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_tenant_id"
name="azure_tenant_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("azureTenantID", e.target.value);
cleanValidation("azure_tenant_id");
}}
label="Tenant ID"
value={azureTenantID}
error={validationErrors["azure_tenant_id"] || ""}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_client_id"
name="azure_client_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("azureClientID", e.target.value);
cleanValidation("azure_client_id");
}}
label="Client ID"
value={azureClientID}
error={validationErrors["azure_client_id"] || ""}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_client_secret"
name="azure_client_secret"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("azureClientSecret", e.target.value);
cleanValidation("azure_client_secret");
}}
label="Client Secret"
value={azureClientSecret}
error={validationErrors["azure_client_secret"] || ""}
/>
<fieldset className={classes.fieldGroup}>
<legend>Credentials</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="azure_tenant_id"
name="azure_tenant_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("azureTenantID", e.target.value);
cleanValidation("azure_tenant_id");
}}
label="Tenant ID"
value={azureTenantID}
error={validationErrors["azure_tenant_id"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="azure_client_id"
name="azure_client_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("azureClientID", e.target.value);
cleanValidation("azure_client_id");
}}
label="Client ID"
value={azureClientID}
error={validationErrors["azure_client_id"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="azure_client_secret"
name="azure_client_secret"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("azureClientSecret", e.target.value);
cleanValidation("azure_client_secret");
}}
label="Client Secret"
value={azureClientSecret}
error={validationErrors["azure_client_secret"] || ""}
/>
</Grid>
</fieldset>
</Grid>
</Fragment>
)}
{encryptionType === "gcp" && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gcp_project_id"
name="gcp_project_id"
@@ -791,7 +834,7 @@ const Encryption = ({
value={gcpProjectID}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gcp_endpoint"
name="gcp_endpoint"
@@ -802,56 +845,60 @@ const Encryption = ({
value={gcpEndpoint}
/>
</Grid>
<h5>Credentials</h5>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_client_email"
name="gcp_client_email"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpClientEmail", e.target.value);
}}
label="Client Email"
value={gcpClientEmail}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_client_id"
name="gcp_client_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpClientID", e.target.value);
}}
label="Client ID"
value={gcpClientID}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_private_key_id"
name="gcp_private_key_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpPrivateKeyID", e.target.value);
}}
label="Private Key ID"
value={gcpPrivateKeyID}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_private_key"
name="gcp_private_key"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpPrivateKey", e.target.value);
}}
label="Private Key"
value={gcpPrivateKey}
/>
<fieldset className={classes.fieldGroup}>
<legend>Credentials</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gcp_client_email"
name="gcp_client_email"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpClientEmail", e.target.value);
}}
label="Client Email"
value={gcpClientEmail}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gcp_client_id"
name="gcp_client_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpClientID", e.target.value);
}}
label="Client ID"
value={gcpClientID}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gcp_private_key_id"
name="gcp_private_key_id"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpPrivateKeyID", e.target.value);
}}
label="Private Key ID"
value={gcpPrivateKeyID}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gcp_private_key"
name="gcp_private_key"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gcpPrivateKey", e.target.value);
}}
label="Private Key"
value={gcpPrivateKey}
/>
</Grid>
</fieldset>
</Grid>
</Fragment>
)}
{encryptionType === "aws" && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="aws_endpoint"
name="aws_endpoint"
@@ -865,7 +912,7 @@ const Encryption = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="aws_region"
name="aws_region"
@@ -879,7 +926,7 @@ const Encryption = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="aws_kmsKey"
name="aws_kmsKey"
@@ -890,51 +937,55 @@ const Encryption = ({
value={awsKMSKey}
/>
</Grid>
<h5>Credentials</h5>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_accessKey"
name="aws_accessKey"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("awsAccessKey", e.target.value);
cleanValidation("aws_accessKey");
}}
label="Access Key"
value={awsAccessKey}
error={validationErrors["aws_accessKey"] || ""}
required
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_secretKey"
name="aws_secretKey"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("awsSecretKey", e.target.value);
cleanValidation("aws_secretKey");
}}
label="Secret Key"
value={awsSecretKey}
error={validationErrors["aws_secretKey"] || ""}
required
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_token"
name="aws_token"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("awsToken", e.target.value);
}}
label="Token"
value={awsToken}
/>
<fieldset className={classes.fieldGroup}>
<legend>Credentials</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="aws_accessKey"
name="aws_accessKey"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("awsAccessKey", e.target.value);
cleanValidation("aws_accessKey");
}}
label="Access Key"
value={awsAccessKey}
error={validationErrors["aws_accessKey"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="aws_secretKey"
name="aws_secretKey"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("awsSecretKey", e.target.value);
cleanValidation("aws_secretKey");
}}
label="Secret Key"
value={awsSecretKey}
error={validationErrors["aws_secretKey"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="aws_token"
name="aws_token"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("awsToken", e.target.value);
}}
label="Token"
value={awsToken}
/>
</Grid>
</fieldset>
</Grid>
</Fragment>
)}
{encryptionType === "gemalto" && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gemalto_endpoint"
name="gemalto_endpoint"
@@ -948,96 +999,116 @@ const Encryption = ({
required
/>
</Grid>
<h5>Credentials</h5>
<Grid item xs={12}>
<InputBoxWrapper
id="gemalto_token"
name="gemalto_token"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gemaltoToken", e.target.value);
cleanValidation("gemalto_token");
}}
label="Token"
value={gemaltoToken}
error={validationErrors["gemalto_token"] || ""}
required
/>
<Grid
item
xs={12}
style={{
marginBottom: 15,
}}
>
<fieldset className={classes.fieldGroup}>
<legend>Credentials</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gemalto_token"
name="gemalto_token"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gemaltoToken", e.target.value);
cleanValidation("gemalto_token");
}}
label="Token"
value={gemaltoToken}
error={validationErrors["gemalto_token"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="gemalto_domain"
name="gemalto_domain"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gemaltoDomain", e.target.value);
cleanValidation("gemalto_domain");
}}
label="Domain"
value={gemaltoDomain}
error={validationErrors["gemalto_domain"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type="number"
min="0"
id="gemalto_retry"
name="gemalto_retry"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gemaltoRetry", e.target.value);
cleanValidation("gemalto_retry");
}}
label="Retry (seconds)"
value={gemaltoRetry}
error={validationErrors["gemalto_retry"] || ""}
/>
</Grid>
</fieldset>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="gemalto_domain"
name="gemalto_domain"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gemaltoDomain", e.target.value);
cleanValidation("gemalto_domain");
}}
label="Domain"
value={gemaltoDomain}
error={validationErrors["gemalto_domain"] || ""}
required
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="0"
id="gemalto_retry"
name="gemalto_retry"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("gemaltoRetry", e.target.value);
cleanValidation("gemalto_retry");
}}
label="Retry (seconds)"
value={gemaltoRetry}
error={validationErrors["gemalto_retry"] || ""}
/>
</Grid>
<h5>Custom CA Root certificate verification</h5>
<Grid item xs={12}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileGemaltoCa(fileName, encodedValue);
cleanValidation("gemalto_ca");
}}
accept=".cer,.crt,.cert,.pem"
id="gemalto_ca"
name="gemalto_ca"
label="CA"
value={gemaltoCA.cert}
/>
<Grid
item
xs={12}
style={{
marginBottom: 15,
}}
>
<fieldset className={classes.fieldGroup}>
<legend>Custom CA Root certificate verification</legend>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileGemaltoCa(fileName, encodedValue);
cleanValidation("gemalto_ca");
}}
accept=".cer,.crt,.cert,.pem"
id="gemalto_ca"
name="gemalto_ca"
label="CA"
value={gemaltoCA.cert}
/>
</fieldset>
</Grid>
</Fragment>
)}
<div className={classes.headerElement}>
<h3 className={classes.h3Section}>Additional Configurations</h3>
<h4 className={classes.h3Section}>Additional Configurations</h4>
</div>
<Grid item xs={12}>
<Fragment>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="1"
id="replicas"
name="replicas"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("replicas", e.target.value);
cleanValidation("replicas");
}}
label="Replicas"
value={replicas}
required
error={validationErrors["replicas"] || ""}
/>
</Grid>
<Grid item xs={12}>
<span className={classes.descriptionText}>
SecurityContext for KES pods
</span>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<Grid item xs={12} classes={classes.formFieldRow}>
<InputBoxWrapper
type="number"
min="1"
id="replicas"
name="replicas"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("replicas", e.target.value);
cleanValidation("replicas");
}}
label="Replicas"
value={replicas}
required
error={validationErrors["replicas"] || ""}
/>
</Grid>
<fieldset className={classes.fieldGroup} style={{ marginTop: 15 }}>
<legend>SecurityContext for KES pods</legend>
<Grid item xs={12} className={classes.kesSecurityContext}>
<div
className={`${classes.multiContainer} ${classes.responsiveContainer}`}
>
<div
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
>
<InputBoxWrapper
type="number"
id="kes_securityContext_runAsUser"
@@ -1058,7 +1129,9 @@ const Encryption = ({
min="0"
/>
</div>
<div>
<div
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
>
<InputBoxWrapper
type="number"
id="kes_securityContext_runAsGroup"
@@ -1079,7 +1152,9 @@ const Encryption = ({
min="0"
/>
</div>
<div>
<div
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
>
<InputBoxWrapper
type="number"
id="kes_securityContext_fsGroup"
@@ -1122,7 +1197,7 @@ const Encryption = ({
/>
</div>
</Grid>
</Fragment>
</fieldset>
</Grid>
</Fragment>
)}

View File

@@ -23,6 +23,8 @@ import { Grid, IconButton, Paper, Tooltip, Typography } from "@mui/material";
import CasinoIcon from "@mui/icons-material/Casino";
import DeleteIcon from "@mui/icons-material/Delete";
import {
createTenantCommon,
formFieldStyles,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -37,6 +39,7 @@ import RadioGroupSelector from "../../../Common/FormComponents/RadioGroupSelecto
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import AddIcon from "@mui/icons-material/Add";
import RemoveIcon from "../../../../../icons/RemoveIcon";
interface IIdentityProviderProps {
classes: any;
@@ -75,15 +78,54 @@ const styles = (theme: Theme) =>
shortened: {
gridTemplateColumns: "auto auto 50px 50px",
display: "grid",
gridGap: 20,
gridGap: 15,
marginBottom: 10,
"& input": {
fontWeight: 400,
},
},
buttonTray: {
gridTemplateColumns: "auto auto 10px 10px",
display: "grid",
gridGap: 0,
height: 16,
marginTop: 12,
marginLeft: 10,
display: "flex",
height: 38,
"& button": {
background: "#EAEAEA",
},
},
overlayAction: {
marginLeft: 10,
"& svg": {
maxWidth: 15,
maxHeight: 15,
},
"& button": {
background: "#EAEAEA",
},
},
protocolRadioOptions: {
display: "flex",
flexFlow: "column",
marginBottom: 10,
"& label": {
fontSize: 14,
},
"& div": {
display: "flex",
flexFlow: "column",
alignItems: "baseline",
},
},
adUserDnRows: {
display: "flex",
},
inputLabel: {
minWidth: 260,
},
...createTenantCommon,
...formFieldStyles,
...modalBasic,
...wizardCommon,
});
@@ -270,46 +312,51 @@ const IdentityProvider = ({
/>
<div className={classes.buttonTray}>
<Tooltip title="Add User" aria-label="add">
<IconButton
size={"small"}
onClick={() => {
accessKeys.push("");
secretKeys.push("");
updateUserField(accessKeys.length - 1, "");
updatePwordField(secretKeys.length - 1, "");
}}
>
<AddIcon />
</IconButton>
</Tooltip>
<Tooltip title="Randomize Credentials" aria-label="add">
<IconButton
onClick={() => {
updateUserField(index, getRandomString(16));
updatePwordField(index, getRandomString(32));
}}
size={"small"}
>
<CasinoIcon />
</IconButton>
<div className={classes.overlayAction}>
<IconButton
size={"small"}
onClick={() => {
accessKeys.push("");
secretKeys.push("");
updateUserField(accessKeys.length - 1, "");
updatePwordField(secretKeys.length - 1, "");
}}
>
<AddIcon />
</IconButton>
</div>
</Tooltip>
<Tooltip title="Remove" aria-label="add">
<IconButton
size={"small"}
style={{ marginLeft: 16 }}
onClick={() => {
if (accessKeys.length > 1) {
accessKeys.splice(index, 1);
secretKeys.splice(index, 1);
updateUserField(
accessKeys.length - 1,
accessKeys[accessKeys.length - 1]
);
}
}}
>
<DeleteIcon />
</IconButton>
<div className={classes.overlayAction}>
<IconButton
size={"small"}
onClick={() => {
if (accessKeys.length > 1) {
accessKeys.splice(index, 1);
secretKeys.splice(index, 1);
updateUserField(
accessKeys.length - 1,
accessKeys[accessKeys.length - 1]
);
}
}}
>
<RemoveIcon />
</IconButton>
</div>
</Tooltip>
<Tooltip title="Randomize Credentials" aria-label="add">
<div className={classes.overlayAction}>
<IconButton
onClick={() => {
updateUserField(index, getRandomString(16));
updatePwordField(index, getRandomString(32));
}}
size={"small"}
>
<CasinoIcon />
</IconButton>
</div>
</Tooltip>
</div>
</div>
@@ -321,11 +368,12 @@ const IdentityProvider = ({
inputs = ADUserDNs.map((_, index) => {
return (
<Fragment key={`identityField-${index.toString()}`}>
<div className={classes.shortened}>
<div className={classes.adUserDnRows}>
<InputBoxWrapper
id={`ad-userdn-${index.toString()}`}
label={""}
placeholder=""
classes={classes}
name={`ad-userdn-${index.toString()}`}
value={ADUserDNs[index]}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -380,12 +428,13 @@ const IdentityProvider = ({
Manager.
</span>
</div>
<Grid item xs={12}>
<Grid item xs={12} className={classes.protocolRadioOptions}>
<label>Protocol</label>
<RadioGroupSelector
currentSelection={idpSelection}
id="idp-options"
name="idp-options"
label="Protocol"
label=" "
onChange={(e) => {
updateField("idpSelection", e.target.value);
}}
@@ -404,7 +453,7 @@ const IdentityProvider = ({
)}
{idpSelection === "OpenID" && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_CONFIGURATION_URL"
name="openID_CONFIGURATION_URL"
@@ -419,7 +468,7 @@ const IdentityProvider = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_clientID"
name="openID_clientID"
@@ -433,7 +482,7 @@ const IdentityProvider = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_secretID"
name="openID_secretID"
@@ -447,7 +496,7 @@ const IdentityProvider = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_callbackURL"
name="openID_callbackURL"
@@ -461,7 +510,7 @@ const IdentityProvider = ({
error={validationErrors["openID_callbackURL"] || ""}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_claimName"
name="openID_claimName"
@@ -475,7 +524,7 @@ const IdentityProvider = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_scopes"
name="openID_scopes"
@@ -491,10 +540,11 @@ const IdentityProvider = ({
)}
{idpSelection === "AD" && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="AD_URL"
name="AD_URL"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADURL", e.target.value);
cleanValidation("AD_URL");
@@ -506,11 +556,12 @@ const IdentityProvider = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_skipTLS"
id="ad_skipTLS"
name="ad_skipTLS"
classes={classes}
checked={ADSkipTLS}
onChange={(e) => {
const targetD = e.target;
@@ -520,11 +571,12 @@ const IdentityProvider = ({
label={"Skip TLS Verification"}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_serverInsecure"
id="ad_serverInsecure"
name="ad_serverInsecure"
classes={classes}
checked={ADServerInsecure}
onChange={(e) => {
const targetD = e.target;
@@ -547,11 +599,12 @@ const IdentityProvider = ({
<br />
</Grid>
) : null}
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_serverStartTLS"
id="ad_serverStartTLS"
name="ad_serverStartTLS"
classes={classes}
checked={ADServerStartTLS}
onChange={(e) => {
const targetD = e.target;
@@ -561,10 +614,11 @@ const IdentityProvider = ({
label={"Start TLS connection to AD/LDAP server"}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userNameFormat"
name="ad_userNameFormat"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADUserNameFormat", e.target.value);
}}
@@ -573,10 +627,11 @@ const IdentityProvider = ({
placeholder="uid=%s,cn=accounts,dc=myldapserver,dc=com"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userNameFilter"
name="ad_userNameFilter"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADUserNameSearchFilter", e.target.value);
}}
@@ -585,10 +640,11 @@ const IdentityProvider = ({
placeholder="(|(objectclass=posixAccount)(uid=%s))"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupSearchBaseDN"
name="ad_groupSearchBaseDN"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADGroupSearchBaseDN", e.target.value);
}}
@@ -597,10 +653,11 @@ const IdentityProvider = ({
placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupSearchFilter"
name="ad_groupSearchFilter"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADGroupSearchFilter", e.target.value);
}}
@@ -609,10 +666,11 @@ const IdentityProvider = ({
placeholder="(&(objectclass=groupOfNames)(member=%s))"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupNameAttribute"
name="ad_groupNameAttribute"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADGroupNameAttribute", e.target.value);
}}
@@ -621,10 +679,11 @@ const IdentityProvider = ({
placeholder="cn"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_lookupBindDN"
name="ad_lookupBindDN"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADLookupBindDN", e.target.value);
}}
@@ -633,10 +692,11 @@ const IdentityProvider = ({
placeholder="cn=admin,dc=min,dc=io"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_lookupBindPassword"
name="ad_lookupBindPassword"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADLookupBindPassword", e.target.value);
}}
@@ -645,10 +705,11 @@ const IdentityProvider = ({
placeholder="admin"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userDNSearchBaseDN"
name="ad_userDNSearchBaseDN"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADUserDNSearchBaseDN", e.target.value);
}}
@@ -657,10 +718,11 @@ const IdentityProvider = ({
placeholder="dc=min,dc=io"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userDNSearchFilter"
name="ad_userDNSearchFilter"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("ADUserDNSearchFilter", e.target.value);
}}
@@ -669,10 +731,14 @@ const IdentityProvider = ({
placeholder="(uid=%s)"
/>
</Grid>
<Grid item xs={12}>
List of user DNs (Distinguished Names) to be Tenant Administrators
{inputs}
</Grid>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
List of user DNs (Distinguished Names) to be Tenant Administrators
</legend>
<Grid item xs={12}>
{inputs}
</Grid>
</fieldset>
</Fragment>
)}
</Paper>

View File

@@ -21,6 +21,7 @@ import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Grid, Paper } from "@mui/material";
import {
formFieldStyles,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -71,6 +72,12 @@ const styles = (theme: Theme) =>
buttonContainer: {
textAlign: "right",
},
inputLabel: {
fontWeight: 300,
fontSize: 14,
minWidth: 200,
},
...formFieldStyles,
...modalBasic,
...wizardCommon,
});
@@ -317,10 +324,11 @@ const Images = ({
</div>
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="image"
name="image"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("imageName", e.target.value);
cleanValidation("image");
@@ -331,10 +339,11 @@ const Images = ({
placeholder="E.g. minio/minio:RELEASE.2021-08-20T18-32-01Z"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="logSearchImage"
name="logSearchImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchImage", e.target.value);
cleanValidation("logSearchImage");
@@ -345,10 +354,11 @@ const Images = ({
placeholder="E.g. minio/logsearchapi:v4.1.1"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="kesImage"
name="kesImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("kesImage", e.target.value);
cleanValidation("kesImage");
@@ -359,10 +369,11 @@ const Images = ({
placeholder="E.g. minio/kes:v0.14.0"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="logSearchPostgresImage"
name="logSearchPostgresImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresImage", e.target.value);
cleanValidation("logSearchPostgresImage");
@@ -373,10 +384,11 @@ const Images = ({
placeholder="E.g. library/postgres:13"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="logSearchPostgresInitImage"
name="logSearchPostgresInitImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresInitImage", e.target.value);
cleanValidation("logSearchPostgresInitImage");
@@ -387,10 +399,11 @@ const Images = ({
placeholder="E.g. library/busybox:1.33.1"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="prometheusImage"
name="prometheusImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusImage", e.target.value);
cleanValidation("prometheusImage");
@@ -401,10 +414,11 @@ const Images = ({
placeholder="E.g. quay.io/prometheus/prometheus:latest"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="prometheusSidecarImage"
name="prometheusSidecarImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSidecarImage", e.target.value);
cleanValidation("prometheusSidecarImage");
@@ -415,10 +429,11 @@ const Images = ({
placeholder="E.g. quay.io/prometheus/prometheus:latest"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="prometheusInitImage"
name="prometheusInitImage"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusInitImage", e.target.value);
cleanValidation("prometheusInitImage");
@@ -433,11 +448,12 @@ const Images = ({
{customImage && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="custom_docker_hub"
id="custom_docker_hub"
name="custom_docker_hub"
classes={classes}
checked={customDockerhub}
onChange={(e) => {
const targetD = e.target;
@@ -452,10 +468,11 @@ const Images = ({
)}
{customDockerhub && (
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="registry"
name="registry"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("imageRegistry", e.target.value);
}}
@@ -466,10 +483,11 @@ const Images = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="registryUsername"
name="registryUsername"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("imageRegistryUsername", e.target.value);
}}
@@ -479,10 +497,11 @@ const Images = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="registryPassword"
name="registryPassword"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("imageRegistryPassword", e.target.value);
}}

View File

@@ -29,6 +29,7 @@ import get from "lodash/get";
import debounce from "lodash/debounce";
import Grid from "@mui/material/Grid";
import {
formFieldStyles,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -65,7 +66,21 @@ const styles = (theme: Theme) =>
},
sizePreview: {
position: "fixed",
marginLeft: 10,
background: "#FFFFFF",
border: "1px solid #EAEAEA",
padding: 2,
},
inputLabel: {
minWidth: 200,
},
errorInField: {
"& .MuiFormControl-root & .MuiOutlinedInput-root & .MuiFormHelperText-root":
{
color: "blue",
},
},
...formFieldStyles,
...modalBasic,
...wizardCommon,
});
@@ -267,7 +282,7 @@ const NameTenant = ({
/>
)}
<Grid container>
<Grid item xs={8}>
<Grid item xs={8} md={9}>
<Paper className={classes.paperWrapper}>
<Grid container>
<Grid item xs={12}>
@@ -277,21 +292,25 @@ const NameTenant = ({
How would you like to name this new tenant?
</span>
</div>
<InputBoxWrapper
id="tenant-name"
name="tenant-name"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantName", e.target.value);
frmValidationCleanup("tenant-name");
}}
label="Name"
value={tenantName}
required
error={validationErrors["tenant-name"] || ""}
/>
<div className={classes.formFieldRow}>
<InputBoxWrapper
id="tenant-name"
classes={classes}
name="tenant-name"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantName", e.target.value);
frmValidationCleanup("tenant-name");
}}
label="Name"
value={tenantName}
required
error={validationErrors["tenant-name"] || ""}
/>
</div>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
classes={classes}
id="namespace"
name="namespace"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -306,8 +325,9 @@ const NameTenant = ({
required
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<SelectWrapper
classes={classes}
id="storage_class"
name="storage_class"
onChange={(e: SelectChangeEvent<string>) => {
@@ -326,7 +346,7 @@ const NameTenant = ({
</Grid>
</Paper>
</Grid>
<Grid item xs={4}>
<Grid item xs={4} md={3}>
<div className={classes.sizePreview}>
<SizePreview />
</div>

View File

@@ -19,8 +19,9 @@ import { connect } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Button, Divider, Grid, Paper, Typography } from "@mui/material";
import { Grid, IconButton, Paper, Typography } from "@mui/material";
import {
createTenantCommon,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -38,6 +39,7 @@ import { AppState } from "../../../../../store";
import { KeyPair } from "../../ListTenants/utils";
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import FileSelector from "../../../Common/FormComponents/FileSelector/FileSelector";
import { AddIcon, RemoveIcon } from "../../../../../icons";
interface ISecurityProps {
classes: any;
@@ -61,6 +63,71 @@ const styles = (theme: Theme) =>
buttonContainer: {
textAlign: "right",
},
minioCertificateRows: {
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
borderBottom: "1px solid #EAEAEA",
"&:last-child": {
borderBottom: 0,
},
"@media (max-width: 900px)": {
flex: 1,
},
},
fileItem: {
marginRight: 10,
display: "flex",
"& div label": {
minWidth: 50,
},
"@media (max-width: 900px)": {
flexFlow: "column",
},
},
fileInputField: {
borderBottom: 0,
},
minioCertsContainer: {
marginBottom: 15,
},
minioCACertsRow: {
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
borderBottom: "1px solid #EAEAEA",
"&:last-child": {
borderBottom: 0,
},
"@media (max-width: 900px)": {
flex: 1,
"& div label": {
minWidth: 50,
},
},
},
rowActions: {
display: "flex",
justifyContent: "flex-end",
"@media (max-width: 900px)": {
flex: 1,
},
},
overlayAction: {
marginLeft: 10,
"& svg": {
maxWidth: 15,
maxHeight: 15,
},
"& button": {
background: "#EAEAEA",
},
},
...createTenantCommon,
...modalBasic,
...wizardCommon,
});
@@ -175,113 +242,133 @@ const Security = ({
{enableCustomCerts && (
<Fragment>
<Grid container>
<Grid item xs={12}>
<Typography variant="overline" display="block" gutterBottom>
MinIO Certificates
</Typography>
</Grid>
{minioCertificates.map((keyPair: KeyPair) => (
<Fragment key={keyPair.id}>
<Grid item xs={5}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileToKeyPair(
keyPair.id,
"cert",
fileName,
encodedValue
);
}}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
</Grid>
<Grid item xs={5}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileToKeyPair(
keyPair.id,
"key",
fileName,
encodedValue
);
}}
accept=".key,.pem"
id="tlsKey"
name="tlsKey"
label="Key"
value={keyPair.key}
/>
</Grid>
<Grid item xs={1}>
<Button
onClick={() => {
deleteKeyPair(keyPair.id);
}}
color="secondary"
<Grid item xs={12} className={classes.minioCertsContainer}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
MinIO Certificates
</legend>
{minioCertificates.map((keyPair: KeyPair) => (
<Grid
item
xs={12}
key={keyPair.id}
className={classes.minioCertificateRows}
>
Remove
</Button>
</Grid>
</Fragment>
))}
<Grid item xs={12}>
<Button onClick={addKeyPair} color="primary">
Add More
</Button>
<Grid item xs={10} className={classes.fileItem}>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileToKeyPair(
keyPair.id,
"cert",
fileName,
encodedValue
);
}}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileToKeyPair(
keyPair.id,
"key",
fileName,
encodedValue
);
}}
accept=".key,.pem"
id="tlsKey"
name="tlsKey"
label="Key"
value={keyPair.key}
/>
</Grid>
<Grid item xs={2} className={classes.rowActions}>
<div className={classes.overlayAction}>
<IconButton size={"small"} onClick={addKeyPair}>
<AddIcon />
</IconButton>
</div>
<div className={classes.overlayAction}>
<IconButton
size={"small"}
onClick={() => {
deleteKeyPair(keyPair.id);
}}
>
<RemoveIcon />
</IconButton>
</div>
</Grid>
</Grid>
))}
</fieldset>
</Grid>
</Grid>
<Grid container>
<Grid item xs={12}>
<br />
<Divider />
<br />
</Grid>
</Grid>
<Grid container>
<Grid item xs={12}>
<Typography variant="overline" display="block" gutterBottom>
MinIO CA Certificates
</Typography>
</Grid>
{caCertificates.map((keyPair: KeyPair) => (
<Fragment key={keyPair.id}>
<Grid item xs={10}>
<FileSelector
onChange={(encodedValue, fileName) => {
addFileToCaCertificates(
keyPair.id,
"cert",
fileName,
encodedValue
);
}}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
</Grid>
<Grid item xs={1}>
<Button
onClick={() => {
deleteCaCertificate(keyPair.id);
}}
color="secondary"
<Grid item xs={12} className={classes.minioCertsContainer}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
MinIO CA Certificates
</legend>
{caCertificates.map((keyPair: KeyPair) => (
<Grid
item
xs={12}
key={keyPair.id}
className={classes.minioCACertsRow}
>
Remove
</Button>
</Grid>
</Fragment>
))}
<Grid item xs={12}>
<Button onClick={addCaCertificate} color="primary">
Add More
</Button>
<Grid item xs={6}>
<FileSelector
classes={classes}
onChange={(encodedValue, fileName) => {
addFileToCaCertificates(
keyPair.id,
"cert",
fileName,
encodedValue
);
}}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
</Grid>
<Grid item xs={6}>
<div className={classes.rowActions}>
<div className={classes.overlayAction}>
<IconButton
size={"small"}
onClick={addCaCertificate}
>
<AddIcon />
</IconButton>
</div>
<div className={classes.overlayAction}>
<IconButton
size={"small"}
onClick={() => {
deleteCaCertificate(keyPair.id);
}}
>
<RemoveIcon />
</IconButton>
</div>
</div>
</Grid>
</Grid>
))}
</fieldset>
</Grid>
</Grid>
</Fragment>

View File

@@ -361,8 +361,10 @@ const SizePreview = ({
</TableCell>
</TableRow>
<TableRow>
<TableCell scope="row">Server Failures Tolerated</TableCell>
<TableCell align="right">
<TableCell style={{ borderBottom: 0 }} scope="row">
Server Failures Tolerated
</TableCell>
<TableCell style={{ borderBottom: 0 }} align="right">
{distribution
? Math.floor(
usableInformation.maxFailureTolerations /

View File

@@ -22,6 +22,7 @@ import withStyles from "@mui/styles/withStyles";
import { AppState } from "../../../../../store";
import { isPageValid, updateAddField } from "../../actions";
import {
formFieldStyles,
modalBasic,
wizardCommon,
} from "../../../Common/FormComponents/common/styleLibrary";
@@ -74,6 +75,25 @@ const styles = (theme: Theme) =>
buttonContainer: {
textAlign: "right",
},
compositeFieldContainer: {
display: "flex",
alignItems: "center",
},
compositeAddOn: {
marginLeft: 10,
"& div": {
marginBottom: 0,
},
"@media (max-width: 900px)": {
"& div": {
marginTop: 5,
},
},
},
inputLabel: {
minWidth: 200,
},
...formFieldStyles,
...modalBasic,
...wizardCommon,
});
@@ -311,11 +331,12 @@ const TenantSize = ({
<div className={classes.error}>{memorySize.error}</div>
</Grid>
)}
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="nodes"
name="nodes"
type="number"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("nodes", e.target.value);
cleanValidation("nodes");
@@ -328,11 +349,12 @@ const TenantSize = ({
error={validationErrors["nodes"] || ""}
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="drivesps"
name="drivesps"
type="number"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("drivesPerServer", e.target.value);
cleanValidation("drivesps");
@@ -347,45 +369,50 @@ const TenantSize = ({
</Grid>
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="volume_size"
name="volume_size"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("volumeSize", e.target.value);
cleanValidation("volume_size");
}}
label="Total Size"
value={volumeSize}
disabled={selectedStorageClass === ""}
required
error={validationErrors["volume_size"] || ""}
min="0"
/>
</div>
<div className={classes.sizeFactorContainer}>
<SelectWrapper
label={"Unit"}
id="size_factor"
name="size_factor"
value={sizeFactor}
disabled={selectedStorageClass === ""}
onChange={(e: SelectChangeEvent<string>) => {
updateField("sizeFactor", e.target.value as string);
}}
options={k8sfactorForDropdown()}
/>
<div className={classes.formFieldRow}>
<div className={classes.compositeFieldContainer}>
<InputBoxWrapper
type="number"
id="volume_size"
name="volume_size"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("volumeSize", e.target.value);
cleanValidation("volume_size");
}}
label="Total Size"
value={volumeSize}
disabled={selectedStorageClass === ""}
required
error={validationErrors["volume_size"] || ""}
min="0"
/>
<div className={classes.compositeAddOn}>
<SelectWrapper
label={""}
id="size_factor"
classes={classes}
name="size_factor"
value={sizeFactor}
disabled={selectedStorageClass === ""}
onChange={(e: SelectChangeEvent<string>) => {
updateField("sizeFactor", e.target.value as string);
}}
options={k8sfactorForDropdown()}
/>
</div>
</div>
</div>
</div>
</Grid>
<Fragment>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type="number"
id="memory_per_node"
name="memory_per_node"
classes={classes}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("memoryNode", e.target.value);
cleanValidation("memory_per_node");
@@ -398,10 +425,11 @@ const TenantSize = ({
min="2"
/>
</Grid>
<Grid item xs={12}>
<Grid item xs={12} className={classes.formFieldRow}>
<SelectWrapper
id="ec_parity"
name="ec_parity"
classes={classes}
onChange={(e: SelectChangeEvent<string>) => {
updateField("ecParity", e.target.value as string);
}}

View File

@@ -28,10 +28,15 @@ import {
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";
import {
deleteDialogStyles,
modalBasic,
} from "../../../../Common/FormComponents/common/styleLibrary";
import { setErrorSnackMessage } from "../../../../../../actions";
import { ErrorResponseHandler } from "../../../../../../common/types";
import api from "../../../../../../common/api";
import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/icons-material/Close";
const styles = (theme: Theme) =>
createStyles({
@@ -41,6 +46,7 @@ const styles = (theme: Theme) =>
wordWrap: "break-word",
},
...modalBasic,
...deleteDialogStyles,
});
interface IAddNamespace {
@@ -90,29 +96,47 @@ const AddNamespaceModal = ({
return (
<Dialog
open={addNamespaceOpen}
classes={classes}
onClose={() => {
closeAddNamespaceModalAndRefresh(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">Create new namespace</DialogTitle>
<DialogTitle id="alert-dialog-title" className={classes.title}>
<div className={classes.titleText}>Create new namespace</div>
<div className={classes.closeContainer}>
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={() => {
closeAddNamespaceModalAndRefresh(false);
}}
disableRipple
size="small"
>
<CloseIcon />
</IconButton>
</div>
</DialogTitle>
<DialogContent>
{addNamespaceLoading && <LinearProgress />}
<DialogContentText id="alert-dialog-description">
Are you sure you want to add a namespace called{" "}
Are you sure you want to add a namespace called
<br />
<b className={classes.wrapText}>{namespace}</b>?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button
type="button"
variant="outlined"
onClick={() => {
closeAddNamespaceModalAndRefresh(false);
}}
color="primary"
disabled={addNamespaceLoading}
type="button"
className={classes.clearButton}
>
Cancel
</Button>
@@ -123,7 +147,7 @@ const AddNamespaceModal = ({
autoFocus
disabled={addNamespaceLoading}
>
Create Namespace
Create
</Button>
</DialogActions>
</Dialog>