Added priority selector to add replication screen (#1396)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2022-01-14 11:33:37 -07:00
committed by GitHub
parent 826cb41392
commit 257f02c554
6 changed files with 68 additions and 9 deletions

View File

@@ -56,6 +56,9 @@ type MultiBucketReplication struct {
// prefix // prefix
Prefix string `json:"prefix,omitempty"` Prefix string `json:"prefix,omitempty"`
// priority
Priority int32 `json:"priority,omitempty"`
// region // region
Region string `json:"region,omitempty"` Region string `json:"region,omitempty"`

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License // 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/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Theme } from "@mui/material/styles"; import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles"; import createStyles from "@mui/styles/createStyles";
@@ -28,7 +28,7 @@ import {
modalStyleUtils, modalStyleUtils,
spacingUtils, spacingUtils,
} from "../../Common/FormComponents/common/styleLibrary"; } from "../../Common/FormComponents/common/styleLibrary";
import { BulkReplicationResponse } from "../types"; import { BucketReplicationRule, BulkReplicationResponse } from "../types";
import { setModalErrorSnackMessage } from "../../../../actions"; import { setModalErrorSnackMessage } from "../../../../actions";
import { ErrorResponseHandler } from "../../../../common/types"; import { ErrorResponseHandler } from "../../../../common/types";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
@@ -46,6 +46,7 @@ interface IReplicationModal {
classes: any; classes: any;
bucketName: string; bucketName: string;
setModalErrorSnackMessage: typeof setModalErrorSnackMessage; setModalErrorSnackMessage: typeof setModalErrorSnackMessage;
setReplicationRules: BucketReplicationRule[];
} }
const styles = (theme: Theme) => const styles = (theme: Theme) =>
@@ -81,8 +82,10 @@ const AddReplicationModal = ({
classes, classes,
bucketName, bucketName,
setModalErrorSnackMessage, setModalErrorSnackMessage,
setReplicationRules,
}: IReplicationModal) => { }: IReplicationModal) => {
const [addLoading, setAddLoading] = useState<boolean>(false); const [addLoading, setAddLoading] = useState<boolean>(false);
const [priority, setPriority] = useState<string>("1");
const [accessKey, setAccessKey] = useState<string>(""); const [accessKey, setAccessKey] = useState<string>("");
const [secretKey, setSecretKey] = useState<string>(""); const [secretKey, setSecretKey] = useState<string>("");
const [targetURL, setTargetURL] = useState<string>(""); const [targetURL, setTargetURL] = useState<string>("");
@@ -99,6 +102,23 @@ const AddReplicationModal = ({
const [bandwidthUnit, setBandwidthUnit] = useState<string>("Gi"); const [bandwidthUnit, setBandwidthUnit] = useState<string>("Gi");
const [healthCheck, setHealthCheck] = useState<string>("60"); const [healthCheck, setHealthCheck] = useState<string>("60");
useEffect(() => {
if (setReplicationRules.length === 0) {
setPriority("1");
return;
}
const greatestValue = setReplicationRules.reduce((prevAcc, currValue) => {
if (currValue.priority > prevAcc) {
return currValue.priority;
}
return prevAcc;
}, 0);
const nextPriority = greatestValue + 1;
setPriority(nextPriority.toString());
}, [setReplicationRules]);
const addRecord = () => { const addRecord = () => {
const replicate = [ const replicate = [
{ {
@@ -127,6 +147,7 @@ const AddReplicationModal = ({
tags: tags, tags: tags,
replicateDeleteMarkers: repDeleteMarker, replicateDeleteMarkers: repDeleteMarker,
replicateDeletes: repDelete, replicateDeletes: repDelete,
priority: parseInt(priority),
}; };
api api
@@ -184,6 +205,20 @@ const AddReplicationModal = ({
> >
<Grid container> <Grid container>
<Grid item xs={12} className={classes.modalFormScrollable}> <Grid item xs={12} className={classes.modalFormScrollable}>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="priority"
name="priority"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.validity.valid) {
setPriority(e.target.value);
}
}}
label="Priority"
value={priority}
pattern={"[0-9]*"}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}> <Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper <InputBoxWrapper
id="targetURL" id="targetURL"

View File

@@ -159,7 +159,7 @@ const BucketReplicationPanel = ({
{ {
type: "delete", type: "delete",
onClick: confirmDeleteReplication, onClick: confirmDeleteReplication,
disableButtonFunction: () => replicationRules.length > 1, disableButtonFunction: () => replicationRules.length === 1,
}, },
]; ];
@@ -170,6 +170,7 @@ const BucketReplicationPanel = ({
closeModalAndRefresh={closeAddReplication} closeModalAndRefresh={closeAddReplication}
open={openSetReplication} open={openSetReplication}
bucketName={bucketName} bucketName={bucketName}
setReplicationRules={replicationRules}
/> />
)} )}

View File

@@ -269,7 +269,7 @@ func addRemoteBucket(ctx context.Context, client MinioAdmin, params models.Creat
return bucketARN, err return bucketARN, err
} }
func addBucketReplicationItem(ctx context.Context, session *models.Principal, minClient minioClient, bucketName, prefix, destinationARN string, repDelMark, repDels, repMeta bool, tags string) error { func addBucketReplicationItem(ctx context.Context, session *models.Principal, minClient minioClient, bucketName, prefix, destinationARN string, repDelMark, repDels, repMeta bool, tags string, priority int32) error {
// we will tolerate this call failing // we will tolerate this call failing
cfg, err := minClient.getBucketReplication(ctx, bucketName) cfg, err := minClient.getBucketReplication(ctx, bucketName)
if err != nil { if err != nil {
@@ -278,12 +278,17 @@ func addBucketReplicationItem(ctx context.Context, session *models.Principal, mi
// add rule // add rule
maxPrio := 0 maxPrio := 0
for _, r := range cfg.Rules {
if r.Priority > maxPrio { if priority <= 0 { // We pick next priority by default
maxPrio = r.Priority for _, r := range cfg.Rules {
if r.Priority > maxPrio {
maxPrio = r.Priority
}
} }
maxPrio++
} else { // User picked priority, we try to set this manually
maxPrio = int(priority)
} }
maxPrio++
s3Client, err := newS3BucketClient(session, bucketName, prefix) s3Client, err := newS3BucketClient(session, bucketName, prefix)
if err != nil { if err != nil {
@@ -366,7 +371,8 @@ func setMultiBucketReplication(ctx context.Context, session *models.Principal, c
params.Body.ReplicateDeleteMarkers, params.Body.ReplicateDeleteMarkers,
params.Body.ReplicateDeletes, params.Body.ReplicateDeletes,
params.Body.ReplicateMetadata, params.Body.ReplicateMetadata,
params.Body.Tags) params.Body.Tags,
params.Body.Priority)
} }
var errorReturn = "" var errorReturn = ""

View File

@@ -4578,6 +4578,11 @@ func init() {
"prefix": { "prefix": {
"type": "string" "type": "string"
}, },
"priority": {
"type": "integer",
"format": "int32",
"default": 0
},
"region": { "region": {
"type": "string" "type": "string"
}, },
@@ -10409,6 +10414,11 @@ func init() {
"prefix": { "prefix": {
"type": "string" "type": "string"
}, },
"priority": {
"type": "integer",
"format": "int32",
"default": 0
},
"region": { "region": {
"type": "string" "type": "string"
}, },

View File

@@ -2967,6 +2967,10 @@ definitions:
type: boolean type: boolean
replicateMetadata: replicateMetadata:
type: boolean type: boolean
priority:
type: integer
format: int32
default: 0
bucketsRelation: bucketsRelation:
type: array type: array
minLength: 1 minLength: 1