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:
@@ -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"`
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -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 = ""
|
||||||
|
|||||||
@@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user