Added replication bulk modal to buckets list (#665)

* Added replication bulk modal to buckets list

* Disabled buttons & inputs in loading state

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2021-04-05 18:20:08 -05:00
committed by GitHub
parent 9c6ed83d63
commit 8a51570d14
44 changed files with 3193 additions and 396 deletions

View File

@@ -0,0 +1,145 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// ListExternalBucketsParams list external buckets params
//
// swagger:model listExternalBucketsParams
type ListExternalBucketsParams struct {
// access key
// Required: true
// Min Length: 3
AccessKey *string `json:"accessKey"`
// region
Region string `json:"region,omitempty"`
// secret key
// Required: true
// Min Length: 8
SecretKey *string `json:"secretKey"`
// target URL
// Required: true
TargetURL *string `json:"targetURL"`
// use TLS
// Required: true
UseTLS *bool `json:"useTLS"`
}
// Validate validates this list external buckets params
func (m *ListExternalBucketsParams) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateAccessKey(formats); err != nil {
res = append(res, err)
}
if err := m.validateSecretKey(formats); err != nil {
res = append(res, err)
}
if err := m.validateTargetURL(formats); err != nil {
res = append(res, err)
}
if err := m.validateUseTLS(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ListExternalBucketsParams) validateAccessKey(formats strfmt.Registry) error {
if err := validate.Required("accessKey", "body", m.AccessKey); err != nil {
return err
}
if err := validate.MinLength("accessKey", "body", string(*m.AccessKey), 3); err != nil {
return err
}
return nil
}
func (m *ListExternalBucketsParams) validateSecretKey(formats strfmt.Registry) error {
if err := validate.Required("secretKey", "body", m.SecretKey); err != nil {
return err
}
if err := validate.MinLength("secretKey", "body", string(*m.SecretKey), 8); err != nil {
return err
}
return nil
}
func (m *ListExternalBucketsParams) validateTargetURL(formats strfmt.Registry) error {
if err := validate.Required("targetURL", "body", m.TargetURL); err != nil {
return err
}
return nil
}
func (m *ListExternalBucketsParams) validateUseTLS(formats strfmt.Registry) error {
if err := validate.Required("useTLS", "body", m.UseTLS); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *ListExternalBucketsParams) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ListExternalBucketsParams) UnmarshalBinary(b []byte) error {
var res ListExternalBucketsParams
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,164 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// MultiBucketReplication multi bucket replication
//
// swagger:model multiBucketReplication
type MultiBucketReplication struct {
// access key
// Required: true
// Min Length: 3
AccessKey *string `json:"accessKey"`
// buckets relation
// Required: true
// Min Length: 1
BucketsRelation []*MultiBucketsRelation `json:"bucketsRelation"`
// region
Region string `json:"region,omitempty"`
// secret key
// Required: true
// Min Length: 8
SecretKey *string `json:"secretKey"`
// target URL
// Required: true
TargetURL *string `json:"targetURL"`
}
// Validate validates this multi bucket replication
func (m *MultiBucketReplication) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateAccessKey(formats); err != nil {
res = append(res, err)
}
if err := m.validateBucketsRelation(formats); err != nil {
res = append(res, err)
}
if err := m.validateSecretKey(formats); err != nil {
res = append(res, err)
}
if err := m.validateTargetURL(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *MultiBucketReplication) validateAccessKey(formats strfmt.Registry) error {
if err := validate.Required("accessKey", "body", m.AccessKey); err != nil {
return err
}
if err := validate.MinLength("accessKey", "body", string(*m.AccessKey), 3); err != nil {
return err
}
return nil
}
func (m *MultiBucketReplication) validateBucketsRelation(formats strfmt.Registry) error {
if err := validate.Required("bucketsRelation", "body", m.BucketsRelation); err != nil {
return err
}
for i := 0; i < len(m.BucketsRelation); i++ {
if swag.IsZero(m.BucketsRelation[i]) { // not required
continue
}
if m.BucketsRelation[i] != nil {
if err := m.BucketsRelation[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("bucketsRelation" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *MultiBucketReplication) validateSecretKey(formats strfmt.Registry) error {
if err := validate.Required("secretKey", "body", m.SecretKey); err != nil {
return err
}
if err := validate.MinLength("secretKey", "body", string(*m.SecretKey), 8); err != nil {
return err
}
return nil
}
func (m *MultiBucketReplication) validateTargetURL(formats strfmt.Registry) error {
if err := validate.Required("targetURL", "body", m.TargetURL); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *MultiBucketReplication) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *MultiBucketReplication) UnmarshalBinary(b []byte) error {
var res MultiBucketReplication
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,66 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// MultiBucketResponseItem multi bucket response item
//
// swagger:model multiBucketResponseItem
type MultiBucketResponseItem struct {
// error string
ErrorString string `json:"errorString,omitempty"`
// origin bucket
OriginBucket string `json:"originBucket,omitempty"`
// target bucket
TargetBucket string `json:"targetBucket,omitempty"`
}
// Validate validates this multi bucket response item
func (m *MultiBucketResponseItem) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *MultiBucketResponseItem) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *MultiBucketResponseItem) UnmarshalBinary(b []byte) error {
var res MultiBucketResponseItem
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,97 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// MultiBucketResponseState multi bucket response state
//
// swagger:model multiBucketResponseState
type MultiBucketResponseState struct {
// replication state
ReplicationState []*MultiBucketResponseItem `json:"replicationState"`
}
// Validate validates this multi bucket response state
func (m *MultiBucketResponseState) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateReplicationState(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *MultiBucketResponseState) validateReplicationState(formats strfmt.Registry) error {
if swag.IsZero(m.ReplicationState) { // not required
return nil
}
for i := 0; i < len(m.ReplicationState); i++ {
if swag.IsZero(m.ReplicationState[i]) { // not required
continue
}
if m.ReplicationState[i] != nil {
if err := m.ReplicationState[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("replicationState" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *MultiBucketResponseState) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *MultiBucketResponseState) UnmarshalBinary(b []byte) error {
var res MultiBucketResponseState
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,63 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// MultiBucketsRelation multi buckets relation
//
// swagger:model multiBucketsRelation
type MultiBucketsRelation struct {
// destination bucket
DestinationBucket string `json:"destinationBucket,omitempty"`
// origin bucket
OriginBucket string `json:"originBucket,omitempty"`
}
// Validate validates this multi buckets relation
func (m *MultiBucketsRelation) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *MultiBucketsRelation) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *MultiBucketsRelation) UnmarshalBinary(b []byte) error {
var res MultiBucketsRelation
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -1,25 +1,25 @@
{
"files": {
"main.css": "/static/css/main.a19f3d53.chunk.css",
"main.js": "/static/js/main.95997f14.chunk.js",
"main.js.map": "/static/js/main.95997f14.chunk.js.map",
"main.js": "/static/js/main.fc2473f5.chunk.js",
"main.js.map": "/static/js/main.fc2473f5.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.f48e99e5.js",
"runtime-main.js.map": "/static/js/runtime-main.f48e99e5.js.map",
"static/css/2.f324abd6.chunk.css": "/static/css/2.f324abd6.chunk.css",
"static/js/2.7b061e18.chunk.js": "/static/js/2.7b061e18.chunk.js",
"static/js/2.7b061e18.chunk.js.map": "/static/js/2.7b061e18.chunk.js.map",
"static/js/2.26e254ca.chunk.js": "/static/js/2.26e254ca.chunk.js",
"static/js/2.26e254ca.chunk.js.map": "/static/js/2.26e254ca.chunk.js.map",
"index.html": "/index.html",
"static/css/2.f324abd6.chunk.css.map": "/static/css/2.f324abd6.chunk.css.map",
"static/css/main.a19f3d53.chunk.css.map": "/static/css/main.a19f3d53.chunk.css.map",
"static/js/2.7b061e18.chunk.js.LICENSE.txt": "/static/js/2.7b061e18.chunk.js.LICENSE.txt",
"static/js/2.26e254ca.chunk.js.LICENSE.txt": "/static/js/2.26e254ca.chunk.js.LICENSE.txt",
"static/media/minio_console_logo.0837460e.svg": "/static/media/minio_console_logo.0837460e.svg",
"static/media/minio_operator_logo.1312b7c9.svg": "/static/media/minio_operator_logo.1312b7c9.svg"
},
"entrypoints": [
"static/js/runtime-main.f48e99e5.js",
"static/css/2.f324abd6.chunk.css",
"static/js/2.7b061e18.chunk.js",
"static/js/2.26e254ca.chunk.js",
"static/css/main.a19f3d53.chunk.css",
"static/js/main.95997f14.chunk.js"
"static/js/main.fc2473f5.chunk.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.f324abd6.chunk.css" rel="stylesheet"><link href="/static/css/main.a19f3d53.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.7b061e18.chunk.js"></script><script src="/static/js/main.95997f14.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.f324abd6.chunk.css" rel="stylesheet"><link href="/static/css/main.a19f3d53.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.26e254ca.chunk.js"></script><script src="/static/js/main.fc2473f5.chunk.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,456 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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, { useState, useEffect, Fragment } from "react";
import { connect } from "react-redux";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { Tooltip } from "@material-ui/core";
import get from "lodash/get";
import Grid from "@material-ui/core/Grid";
import ErrorOutlineIcon from "@material-ui/icons/ErrorOutline";
import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline";
import {
modalBasic,
wizardCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import { setModalErrorSnackMessage } from "../../../../actions";
import { BulkReplicationResponse, BulkReplicationItem } from "../types";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import PredefinedList from "../../Common/FormComponents/PredefinedList/PredefinedList";
import api from "../../../../common/api";
import GenericWizard from "../../Common/GenericWizard/GenericWizard";
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper";
import { SelectorTypes } from "../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
interface IBulkReplicationModal {
open: boolean;
closeModalAndRefresh: (clearSelection: boolean) => any;
classes: any;
buckets: string[];
setModalErrorSnackMessage: typeof setModalErrorSnackMessage;
}
const styles = (theme: Theme) =>
createStyles({
minTableHeader: {
color: "#393939",
"& tr": {
"& th": {
fontWeight: "bold",
},
},
},
buttonContainer: {
textAlign: "right",
},
remoteBucketList: {
display: "grid",
gridTemplateColumns: "auto auto 45px",
alignItems: "center",
justifyContent: "stretch",
},
errorIcon: {
color: "#C72C48",
},
successIcon: {
color: "#42C91A",
},
hide: {
opacity: 0,
transitionDuration: "0.3s",
},
...modalBasic,
...wizardCommon,
});
const AddBulkReplicationModal = ({
open,
closeModalAndRefresh,
classes,
buckets,
setModalErrorSnackMessage,
}: IBulkReplicationModal) => {
const [bucketsToAlter, setBucketsToAlter] = useState<string[]>([]);
const [addLoading, setAddLoading] = useState<boolean>(false);
const [externalLoading, setExternalLoading] = useState<boolean>(false);
const [accessKey, setAccessKey] = useState<string>("");
const [secretKey, setSecretKey] = useState<string>("");
const [targetURL, setTargetURL] = useState<string>("");
const [region, setRegion] = useState<string>("");
const [useTLS, setUseTLS] = useState<boolean>(true);
const [relationBuckets, setRelationBuckets] = useState<string[]>([]);
const [remoteBucketsOpts, setRemoteBucketOpts] = useState<string[]>([]);
const [responseItem, setResponseItem] = useState<BulkReplicationItem[]>([]);
const optionsForBucketsDrop: SelectorTypes[] = remoteBucketsOpts.map(
(remoteBucketName: string) => {
return {
label: remoteBucketName,
value: remoteBucketName,
};
}
);
useEffect(() => {
if (relationBuckets.length === 0) {
const bucketsAlter: string[] = [];
const relationBucketsAlter: string[] = [];
buckets.forEach((item: string) => {
bucketsAlter.push(item);
relationBucketsAlter.push("");
});
setRelationBuckets(relationBucketsAlter);
setBucketsToAlter(bucketsAlter);
}
}, [buckets, relationBuckets.length]);
const addRecord = () => {
setAddLoading(true);
const replicate = bucketsToAlter.map((bucketName, index) => {
return {
originBucket: bucketName,
destinationBucket: relationBuckets[index],
};
});
const endURL = `${useTLS ? "https://" : "http://"}${targetURL}`;
const remoteBucketsInfo = {
accessKey: accessKey,
secretKey: secretKey,
targetURL: endURL,
region: region,
bucketsRelation: replicate,
};
api
.invoke("POST", "/api/v1/buckets-replication", remoteBucketsInfo)
.then((response: BulkReplicationResponse) => {
setAddLoading(false);
const states = response.replicationState;
setResponseItem(states);
const filterErrors = states.filter(
(itm) => itm.errorString && itm.errorString !== ""
);
if (filterErrors.length === 0) {
closeModalAndRefresh(true);
} else {
setTimeout(() => {
removeSuccessItems(states);
}, 500);
}
})
.catch((err) => {
setAddLoading(false);
setModalErrorSnackMessage(err);
});
};
const retrieveRemoteBuckets = (
wizardPageJump: (page: number | string) => void
) => {
const remoteConnectInfo = {
accessKey: accessKey,
secretKey: secretKey,
targetURL: targetURL,
useTLS,
};
setExternalLoading(true);
api
.invoke("POST", "api/v1/list-external-buckets", remoteConnectInfo)
.then((dataReturn) => {
const buckets = get(dataReturn, "buckets", []);
if (buckets && buckets.length > 0) {
const arrayReplaceBuckets = buckets.map((element: any) => {
return element.name;
});
setRemoteBucketOpts(arrayReplaceBuckets);
}
wizardPageJump("++");
setExternalLoading(false);
})
.catch((err) => {
setExternalLoading(false);
setModalErrorSnackMessage(err);
});
};
const stateOfItem = (initialBucket: string) => {
if (responseItem.length > 0) {
const bucketResponse = responseItem.find(
(item) => item.originBucket === initialBucket
);
if (bucketResponse) {
const errString = get(bucketResponse, "errorString", "");
if (errString) {
return errString;
}
return "";
}
}
return "n/a";
};
const LogoToShow = ({ errString }: { errString: string }) => {
switch (errString) {
case "":
return (
<div className={classes.successIcon}>
<CheckCircleOutlineIcon />
</div>
);
case "n/a":
return null;
default:
if (errString) {
return (
<div className={classes.errorIcon}>
<Tooltip title={errString} placement="top-start">
<ErrorOutlineIcon />
</Tooltip>
</div>
);
}
}
return null;
};
const updateItem = (indexItem: number, value: string) => {
const updatedList = [...relationBuckets];
updatedList[indexItem] = value;
setRelationBuckets(updatedList);
};
const itemDisplayBulk = (indexItem: number) => {
if (remoteBucketsOpts.length > 0) {
return (
<Fragment>
<SelectWrapper
label=""
id={`assign-bucket-${indexItem}`}
name={`assign-bucket-${indexItem}`}
value={relationBuckets[indexItem]}
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
updateItem(indexItem, e.target.value as string);
}}
options={optionsForBucketsDrop}
disabled={addLoading}
/>
</Fragment>
);
}
return (
<Fragment>
<InputBoxWrapper
id={`assign-bucket-${indexItem}`}
name={`assign-bucket-${indexItem}`}
label=""
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
updateItem(indexItem, event.target.value);
}}
value={relationBuckets[indexItem]}
disabled={addLoading}
/>
</Fragment>
);
};
const removeSuccessItems = (responseItem: BulkReplicationItem[]) => {
let newBucketsToAlter = [...bucketsToAlter];
let newRelationBuckets = [...relationBuckets];
responseItem.forEach((successElement) => {
const errorString = get(successElement, "errorString", "");
if (!errorString || errorString === "") {
const indexToRemove = newBucketsToAlter.indexOf(
successElement.originBucket
);
newBucketsToAlter.splice(indexToRemove, 1);
newRelationBuckets.splice(indexToRemove, 1);
}
});
setBucketsToAlter(newBucketsToAlter);
setRelationBuckets(newRelationBuckets);
};
return (
<ModalWrapper
modalOpen={open}
onClose={() => {
closeModalAndRefresh(false);
}}
title="Set Multiple Bucket Replication"
>
<GenericWizard
loadingStep={addLoading || externalLoading}
wizardSteps={[
{
label: "Remote Configuration",
componentRender: (
<Fragment>
<Grid item xs={12}>
<PredefinedList
label="Local Buckets to replicate"
content={bucketsToAlter.join(", ")}
/>
</Grid>
<h4>Remote Endpoint Configuration</h4>
<span className={classes.descriptionText}>
Please avoid the use of root credentials for this feature
</span><br /><br />
<Grid item xs={12}>
<InputBoxWrapper
id="accessKey"
name="accessKey"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setAccessKey(e.target.value);
}}
label="Access Key"
value={accessKey}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="secretKey"
name="secretKey"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setSecretKey(e.target.value);
}}
label="Secret Key"
value={secretKey}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="targetURL"
name="targetURL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTargetURL(e.target.value);
}}
placeholder="play.min.io:9000"
label="Target URL"
value={targetURL}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
checked={useTLS}
id="useTLS"
name="useTLS"
label="Use TLS"
onChange={(e) => {
setUseTLS(e.target.checked);
}}
value="yes"
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
id="region"
name="region"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setRegion(e.target.value);
}}
label="Region"
value={region}
/>
</Grid>
</Fragment>
),
buttons: [
{
type: "custom",
label: "Next",
enabled: !externalLoading,
action: retrieveRemoteBuckets,
},
],
},
{
label: "Buckets Assignation",
componentRender: (
<Fragment>
<h3>Remote Buckets Assignation</h3>
<span className={classes.descriptionText}>
Please select / type the desired remote bucket were you want
the local data to be replicated.
</span>
<div className={classes.remoteBucketList}>
{bucketsToAlter.map((bucketName: string, index: number) => {
const errorItem = stateOfItem(bucketName);
return (
<Fragment
key={`buckets-assignation-${index.toString()}-${bucketName}`}
>
<div className={errorItem === "" ? classes.hide : ""}>
{bucketName}
</div>
<div className={errorItem === "" ? classes.hide : ""}>
{itemDisplayBulk(index)}
</div>
<div className={errorItem === "" ? classes.hide : ""}>
{responseItem.length > 0 && (
<LogoToShow errString={errorItem} />
)}
</div>
</Fragment>
);
})}
</div>
</Fragment>
),
buttons: [
{
type: "back",
label: "Back",
enabled: true,
},
{
type: "next",
label: "Create",
enabled: !addLoading,
action: addRecord,
},
],
},
]}
forModal
/>
</ModalWrapper>
);
};
const connector = connect(null, {
setModalErrorSnackMessage,
});
export default withStyles(styles)(connector(AddBulkReplicationModal));

View File

@@ -22,6 +22,7 @@ import Grid from "@material-ui/core/Grid";
import TextField from "@material-ui/core/TextField";
import InputAdornment from "@material-ui/core/InputAdornment";
import SearchIcon from "@material-ui/icons/Search";
import FileCopyIcon from "@material-ui/icons/FileCopy";
import Moment from "react-moment";
import { Bucket, BucketList, HasPermissionResponse } from "../types";
import { CreateIcon } from "../../../../icons";
@@ -39,6 +40,7 @@ import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import AddBucket from "./AddBucket";
import DeleteBucket from "./DeleteBucket";
import PageHeader from "../../Common/PageHeader/PageHeader";
import BulkReplicationModal from "./BulkReplicationModal";
const styles = (theme: Theme) =>
createStyles({
@@ -94,6 +96,10 @@ const ListBuckets = ({
const [filterBuckets, setFilterBuckets] = useState<string>("");
const [loadingPerms, setLoadingPerms] = useState<boolean>(true);
const [canCreateBucket, setCanCreateBucket] = useState<boolean>(false);
const [selectedBuckets, setSelectedBuckets] = useState<string[]>([]);
const [replicationModalOpen, setReplicationModalOpen] = useState<boolean>(
false
);
// check the permissions for creating bucket
useEffect(() => {
@@ -114,7 +120,7 @@ const ListBuckets = ({
}
const actions = res.permissions ? res.permissions : [];
let canCreate = actions.find((s) => s.id == "createBucket");
let canCreate = actions.find((s) => s.id === "createBucket");
if (canCreate && canCreate.can) {
setCanCreateBucket(true);
} else {
@@ -155,6 +161,7 @@ const ListBuckets = ({
if (refresh) {
setLoading(true);
setSelectedBuckets([]);
}
};
@@ -162,6 +169,7 @@ const ListBuckets = ({
setDeleteOpen(false);
if (refresh) {
setLoading(true);
setSelectedBuckets([]);
}
};
@@ -191,6 +199,33 @@ const ListBuckets = ({
}
});
const selectListBuckets = (e: React.ChangeEvent<HTMLInputElement>) => {
const targetD = e.target;
const value = targetD.value;
const checked = targetD.checked;
let elements: string[] = [...selectedBuckets]; // We clone the selectedBuckets array
if (checked) {
// If the user has checked this field we need to push this to selectedBucketsList
elements.push(value);
} else {
// User has unchecked this field, we need to remove it from the list
elements = elements.filter((element) => element !== value);
}
setSelectedBuckets(elements);
return elements;
};
const closeBulkReplicationModal = (unselectAll: boolean) => {
setReplicationModalOpen(false);
if (unselectAll) {
setSelectedBuckets([]);
}
};
return (
<Fragment>
{addBucketModalOpen && (
@@ -208,6 +243,13 @@ const ListBuckets = ({
}}
/>
)}
{replicationModalOpen && (
<BulkReplicationModal
open={replicationModalOpen}
buckets={selectedBuckets}
closeModalAndRefresh={closeBulkReplicationModal}
/>
)}
<PageHeader label={"Buckets"} />
<Grid container>
<Grid item xs={12} className={classes.container}>
@@ -229,6 +271,17 @@ const ListBuckets = ({
),
}}
/>
<Button
variant="contained"
color="primary"
startIcon={<FileCopyIcon />}
onClick={() => {
setReplicationModalOpen(true);
}}
disabled={selectedBuckets.length === 0}
>
Set Replication
</Button>
{canCreateBucket && (
<Button
variant="contained"
@@ -267,6 +320,8 @@ const ListBuckets = ({
records={filteredRecords}
entityName="Buckets"
idField="name"
selectedItems={selectedBuckets}
onSelect={selectListBuckets}
/>
</Grid>
</Grid>

View File

@@ -21,7 +21,7 @@ import { Button, LinearProgress } from "@material-ui/core";
import get from "lodash/get";
import Grid from "@material-ui/core/Grid";
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
import { IRemoteBucket } from "../types";
import { BulkReplicationResponse } from "../types";
import { setModalErrorSnackMessage } from "../../../../actions";
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
@@ -66,52 +66,43 @@ const AddReplicationModal = ({
const [region, setRegion] = useState("");
const addRecord = () => {
const remoteBucketInfo = {
const replicate = [
{
originBucket: bucketName,
destinationBucket: targetBucket,
},
];
const remoteBucketsInfo = {
accessKey: accessKey,
secretKey: secretKey,
sourceBucket: bucketName,
targetURL: targetURL,
targetBucket: targetBucket,
region: region,
bucketsRelation: replicate,
};
api
.invoke("POST", "/api/v1/remote-buckets", remoteBucketInfo)
.then(() => {
api
.invoke("GET", "/api/v1/remote-buckets")
.then((res: any) => {
const remoteBuckets = get(res, "buckets", []);
const remoteBucket = remoteBuckets.find(
(itemRemote: IRemoteBucket) => {
return itemRemote.sourceBucket === bucketName;
}
);
if (remoteBucket && remoteBucket.remoteARN) {
const remoteARN = remoteBucket.remoteARN;
const replicationInfo = {
destination_bucket: targetBucket,
arn: remoteARN,
};
api
.invoke(
"POST",
`/api/v1/buckets/${bucketName}/replication`,
replicationInfo
)
.then(() => {
setAddLoading(false);
closeModalAndRefresh();
})
.catch((err) => {
setAddLoading(false);
setModalErrorSnackMessage(err);
});
}
})
.catch((err) => {
setModalErrorSnackMessage(err);
});
.invoke("POST", "/api/v1/buckets-replication", remoteBucketsInfo)
.then((response: BulkReplicationResponse) => {
setAddLoading(false);
const states = get(response, "replicationState", []);
if (states.length > 0) {
const itemVal = states[0];
setAddLoading(false);
if (itemVal.errorString && itemVal.errorString !== "") {
setModalErrorSnackMessage(itemVal.errorString);
return;
}
closeModalAndRefresh();
return;
}
setModalErrorSnackMessage("No changes applied");
})
.catch((err) => {
setAddLoading(false);

View File

@@ -0,0 +1,117 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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, { useState } from "react";
import { connect } from "react-redux";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress,
} from "@material-ui/core";
import { setErrorSnackMessage } from "../../../../actions";
import api from "../../../../common/api";
interface IDeleteReplicationProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
deleteOpen: boolean;
selectedBucket: string;
ruleToDelete: string;
setErrorSnackMessage: typeof setErrorSnackMessage;
}
const DeleteReplicationRule = ({
closeDeleteModalAndRefresh,
deleteOpen,
selectedBucket,
ruleToDelete,
setErrorSnackMessage,
}: IDeleteReplicationProps) => {
const [deleteLoading, setDeleteLoading] = useState<boolean>(false);
const removeRecord = () => {
if (!deleteLoading) {
setDeleteLoading(true);
api
.invoke(
"DELETE",
`/api/v1/buckets/${selectedBucket}/replication/${ruleToDelete}`
)
.then(() => {
setDeleteLoading(false);
closeDeleteModalAndRefresh(true);
})
.catch((err) => {
setDeleteLoading(false);
setErrorSnackMessage(err);
});
}
};
return (
<Dialog
open={deleteOpen}
onClose={() => {
closeDeleteModalAndRefresh(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">Delete Replication Rule</DialogTitle>
<DialogContent>
{deleteLoading && <LinearProgress />}
<DialogContentText id="alert-dialog-description">
Are you sure you want to delete replication rule <b>{ruleToDelete}</b>
? <br />
Remember, at lease one rule must be present once replication has been
enabled
</DialogContentText>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
closeDeleteModalAndRefresh(false);
}}
color="primary"
disabled={deleteLoading}
>
Cancel
</Button>
<Button
onClick={() => {
removeRecord();
}}
color="secondary"
autoFocus
>
Delete
</Button>
</DialogActions>
</Dialog>
);
};
const mapDispatchToProps = {
setErrorSnackMessage,
};
const connector = connect(null, mapDispatchToProps);
export default connector(DeleteReplicationRule);

View File

@@ -25,6 +25,7 @@ import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
import CircularProgress from "@material-ui/core/CircularProgress";
import Checkbox from "@material-ui/core/Checkbox";
import Typography from "@material-ui/core/Typography";
import api from "../../../../common/api";
import {
BucketEncryptionInfo,
@@ -44,6 +45,8 @@ import { CreateIcon } from "../../../../icons";
import { niceBytes } from "../../../../common/utils";
import { containerForHeader } from "../../Common/FormComponents/common/styleLibrary";
import { setErrorSnackMessage } from "../../../../actions";
import { Policy } from "../../Policies/types";
import { User } from "../../Users/types";
import SetRetentionConfig from "./SetRetentionConfig";
import AddEvent from "./AddEvent";
import DeleteEvent from "./DeleteEvent";
@@ -53,12 +56,11 @@ import PageHeader from "../../Common/PageHeader/PageHeader";
import EnableBucketEncryption from "./EnableBucketEncryption";
import PencilIcon from "../../Common/TableWrapper/TableActionIcons/PencilIcon";
import EnableVersioningModal from "./EnableVersioningModal";
import Typography from "@material-ui/core/Typography";
import UsageIcon from "../../../../icons/UsageIcon";
import AddPolicy from "../../Policies/AddPolicy";
import SetAccessPolicy from "./SetAccessPolicy";
import { Policy } from "../../Policies/types";
import { User } from "../../Users/types";
import DeleteReplicationRule from "../ViewBucket/DeleteReplicationRule";
const styles = (theme: Theme) =>
createStyles({
@@ -259,6 +261,10 @@ const ViewBucket = ({
const [loadingPerms, setLoadingPerms] = useState<boolean>(true);
const [canPutReplication, setCanPutReplication] = useState<boolean>(false);
const [canGetReplication, setCanGetReplication] = useState<boolean>(false);
const [deleteReplicationModal, setDeleteReplicationModal] = useState<boolean>(
false
);
const [selectedRRule, setSelectedRRule] = useState<string>("");
// check the permissions for creating bucket
useEffect(() => {
@@ -286,7 +292,7 @@ const ViewBucket = ({
const actions = res.permissions ? res.permissions : [];
let canPutReplication = actions.find(
(s) => s.id == "PutReplicationConfiguration"
(s) => s.id === "PutReplicationConfiguration"
);
if (canPutReplication && canPutReplication.can) {
@@ -295,7 +301,7 @@ const ViewBucket = ({
setCanPutReplication(false);
}
let canGetReplication = actions.find(
(s) => s.id == "GetReplicationConfiguration"
(s) => s.id === "GetReplicationConfiguration"
);
if (canGetReplication && canGetReplication.can) {
@@ -523,6 +529,11 @@ const ViewBucket = ({
setSelectedEvent(evnt);
};
const confirmDeleteReplication = (replication: BucketReplicationRule) => {
setSelectedRRule(replication.id);
setDeleteReplicationModal(true);
};
const closeEnableVersioning = (refresh: boolean) => {
setEnableVersioningOpen(false);
if (refresh) {
@@ -552,6 +563,14 @@ const ViewBucket = ({
setOpenSetReplication(open);
};
const closeReplicationModalDelete = (refresh: boolean) => {
setDeleteReplicationModal(false);
if (refresh) {
setLoadingReplication(true);
}
};
const handleEncryptionCheckbox = (
event: React.ChangeEvent<HTMLInputElement>
) => {
@@ -576,6 +595,13 @@ const ViewBucket = ({
};
const PolicyActions = [{ type: "view", onClick: viewAction }];
const replicationTableActions = [
{
type: "delete",
onClick: confirmDeleteReplication,
hideButtonFunction: () => replicationRules.length <= 1,
},
];
return (
<Fragment>
@@ -638,6 +664,14 @@ const ViewBucket = ({
versioningCurrentState={isVersioned}
/>
)}
{deleteReplicationModal && (
<DeleteReplicationRule
deleteOpen={deleteReplicationModal}
selectedBucket={bucketName}
closeDeleteModalAndRefresh={closeReplicationModalDelete}
ruleToDelete={selectedRRule}
/>
)}
<PageHeader label={`Bucket > ${match.params["bucketName"]}`} />
<Grid container>
<Grid item xs={12} className={classes.container}>
@@ -850,7 +884,7 @@ const ViewBucket = ({
{canGetReplication && (
<TabPanel index={1} value={curTab}>
<TableWrapper
itemActions={tableActions}
itemActions={replicationTableActions}
columns={[
{ label: "ID", elementKey: "id" },
{
@@ -863,7 +897,7 @@ const ViewBucket = ({
renderFunction: ruleDestDisplay,
},
{
label: "Delete Replication",
label: "Delete Marker Replication",
elementKey: "delete_marker_replication",
renderFunction: ruleDelDisplay,
},

View File

@@ -132,3 +132,13 @@ export interface PermissionAction {
export interface HasPermissionResponse {
permissions: PermissionAction[];
}
export interface BulkReplicationResponse {
replicationState: BulkReplicationItem[];
}
export interface BulkReplicationItem {
errorString: string;
originBucket: string;
targetBucket: string;
}

View File

@@ -14,7 +14,7 @@
// 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, { useState } from "react";
import React, { useState, Fragment } from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { IWizardMain } from "./types";
import WizardPage from "./WizardPage";
@@ -43,7 +43,7 @@ const styles = (theme: Theme) =>
height: "100%",
"& ul": {
padding: "0 15px 0 40px",
marginTop: "0px",
marginTop: 0,
"& li": {
listStyle: "lower-roman",
@@ -51,6 +51,23 @@ const styles = (theme: Theme) =>
},
},
},
modalWizardSteps: {
padding: 5,
borderBottom: "#eaeaea 1px solid",
"& ul": {
padding: 0,
marginTop: 0,
display: "flex",
justifyContent: "space-evenly",
"& li": {
listStyle: "lower-roman",
"&::marker": {
paddingLeft: 15,
},
},
},
},
buttonList: {
backgroundColor: "transparent",
border: "none",
@@ -72,10 +89,28 @@ const styles = (theme: Theme) =>
color: "#393939",
fontWeight: 600,
margin: "15px 12px",
"&.stepsModalTitle": {
textAlign: "center",
width: "100%",
marginTop: 0,
marginBottom: 10,
},
},
stepsMasterContainer: {
position: "sticky",
top: 0,
backgroundColor: "#FFFFFF",
width: "100%",
maxHeight: 90,
},
});
const GenericWizard = ({ classes, wizardSteps }: IWizardMain) => {
const GenericWizard = ({
classes,
wizardSteps,
loadingStep,
forModal,
}: IWizardMain) => {
const [currentStep, setCurrentStep] = useState<number>(0);
const pageChange = (toElement: string | number) => {
@@ -119,38 +154,61 @@ const GenericWizard = ({ classes, wizardSteps }: IWizardMain) => {
return null;
}
const stepsList = () => {
return (
<ul>
{wizardSteps.map((step, index) => {
return (
<li key={`wizard-${index.toString()}`}>
<button
onClick={() => pageChange(index)}
disabled={index > currentStep}
className={classes.buttonList}
>
{step.label}
</button>
</li>
);
})}
</ul>
);
};
return (
<Grid container className={classes.wizFromContainer}>
<Grid item xs={12} sm={3} md={3} lg={3} xl={2}>
<div className={classes.wizardSteps}>
<span className={classes.stepsLabel}>Steps</span>
<ul>
{wizardSteps.map((step, index) => {
return (
<li key={`wizard-${index.toString()}`}>
<button
onClick={() => pageChange(index)}
disabled={index > currentStep}
className={classes.buttonList}
>
{step.label}
</button>
</li>
);
})}
</ul>
</div>
</Grid>
{forModal ? (
<Fragment>
<div className={classes.stepsMasterContainer}>
<div className={`${classes.stepsLabel} stepsModalTitle`}>Steps</div>
<div className={classes.modalWizardSteps}>{stepsList()}</div>
</div>
</Fragment>
) : (
<Fragment>
<Grid item xs={12} sm={3} md={3} lg={3} xl={2}>
<div className={classes.wizardSteps}>
<span className={classes.stepsLabel}>Steps</span>
{stepsList()}
</div>
</Grid>
</Fragment>
)}
<Grid
item
xs={12}
sm={9}
md={9}
lg={9}
xl={10}
sm={forModal ? 12 : 9}
md={forModal ? 12 : 9}
lg={forModal ? 12 : 9}
xl={forModal ? 12 : 10}
className={classes.paddedContentGrid}
>
<WizardPage page={wizardSteps[currentStep]} pageChange={pageChange} />
<WizardPage
page={wizardSteps[currentStep]}
pageChange={pageChange}
loadingStep={loadingStep}
forModal
/>
</Grid>
</Grid>
);

View File

@@ -17,7 +17,7 @@
import React from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { IWizardButton, IWizardPage } from "./types";
import { Button } from "@material-ui/core";
import { Button, LinearProgress } from "@material-ui/core";
const styles = (theme: Theme) =>
createStyles({
@@ -33,6 +33,11 @@ const styles = (theme: Theme) =>
margin: "0 auto",
width: "100%",
},
wizardModal: {
overflowY: "auto",
marginBottom: 10,
height: "calc(100vh - 515px)",
},
buttonsContainer: {
display: "flex",
flexDirection: "row",
@@ -45,7 +50,13 @@ const styles = (theme: Theme) =>
},
});
const WizardPage = ({ classes, page, pageChange }: IWizardPage) => {
const WizardPage = ({
classes,
page,
pageChange,
loadingStep,
forModal,
}: IWizardPage) => {
const buttonAction = (btn: IWizardButton) => {
switch (btn.type) {
case "next":
@@ -57,17 +68,25 @@ const WizardPage = ({ classes, page, pageChange }: IWizardPage) => {
case "to":
pageChange(btn.toPage || 0);
break;
case "custom":
default:
}
if (btn.action) {
btn.action();
btn.action(pageChange);
}
};
return (
<div className={classes.wizardStepContainer}>
<div className={classes.wizardComponent}>{page.componentRender}</div>
<div className={forModal ? classes.wizardModal : classes.wizardComponent}>
{page.componentRender}
</div>
{loadingStep && (
<div>
<LinearProgress />
</div>
)}
<div className={classes.buttonsContainer}>
{page.buttons.map((btn) => {
return (

View File

@@ -17,7 +17,7 @@
export interface IWizardButton {
label: string;
type: string;
action?: () => void;
action?: (nextFunction: (to: string | number) => void) => void;
enabled?: boolean;
toPage?: number;
}
@@ -27,15 +27,20 @@ export interface IWizardElement {
componentRender: any;
buttons: IWizardButton[];
advancedOnly?: boolean;
loadingStep?: boolean;
}
export interface IWizardMain {
classes: any;
loadingStep?: boolean;
wizardSteps: IWizardElement[];
forModal?: boolean;
}
export interface IWizardPage {
classes: any;
page: IWizardElement;
pageChange: (to: string | number) => void;
loadingStep?: boolean;
forModal?: boolean;
}

View File

@@ -32,6 +32,7 @@ interface IModalProps {
children: any;
wideLimit?: boolean;
modalSnackMessage?: snackBarMessage;
noContentPadding?: boolean;
setModalSnackMessage: typeof setModalSnackMessage;
}
@@ -114,6 +115,7 @@ const ModalWrapper = ({
classes,
wideLimit = true,
modalSnackMessage,
noContentPadding,
setModalSnackMessage,
}: IModalProps) => {
const [openSnackbar, setOpenSnackbar] = useState<boolean>(false);
@@ -184,7 +186,7 @@ const ModalWrapper = ({
<DialogTitle id="alert-dialog-title" className={classes.titleClass}>
{title}
</DialogTitle>
<DialogContent className={classes.modalContent}>
<DialogContent className={noContentPadding ? "" : classes.modalContent}>
{children}
</DialogContent>
</div>

View File

@@ -19,19 +19,28 @@ package restapi
import (
"context"
"errors"
"fmt"
"log"
"net/url"
"strconv"
"time"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/restapi/operations/user_api"
"github.com/minio/minio-go/v7/pkg/replication"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/madmin"
)
type RemoteBucketResult struct {
OriginBucket string
TargetBucket string
Error string
}
func registerAdminBucketRemoteHandlers(api *operations.ConsoleAPI) {
// return list of remote buckets
api.UserAPIListRemoteBucketsHandler = user_api.ListRemoteBucketsHandlerFunc(func(params user_api.ListRemoteBucketsParams, session *models.Principal) middleware.Responder {
@@ -69,6 +78,38 @@ func registerAdminBucketRemoteHandlers(api *operations.ConsoleAPI) {
return user_api.NewAddRemoteBucketCreated()
})
// set multi-bucket replication
api.UserAPISetMultiBucketReplicationHandler = user_api.SetMultiBucketReplicationHandlerFunc(func(params user_api.SetMultiBucketReplicationParams, session *models.Principal) middleware.Responder {
response, err := setMultiBucketReplicationResponse(session, params)
if err != nil {
return user_api.NewSetMultiBucketReplicationDefault(500).WithPayload(err)
}
return user_api.NewSetMultiBucketReplicationOK().WithPayload(response)
})
// list external buckets
api.UserAPIListExternalBucketsHandler = user_api.ListExternalBucketsHandlerFunc(func(params user_api.ListExternalBucketsParams, session *models.Principal) middleware.Responder {
response, err := listExternalBucketsResponse(params)
if err != nil {
return user_api.NewListExternalBucketsDefault(500).WithPayload(err)
}
return user_api.NewListExternalBucketsOK().WithPayload(response)
})
// delete replication rule
api.UserAPIDeleteBucketReplicationRuleHandler = user_api.DeleteBucketReplicationRuleHandlerFunc(func(params user_api.DeleteBucketReplicationRuleParams, session *models.Principal) middleware.Responder {
err := deleteReplicationRuleResponse(session, params)
if err != nil {
return user_api.NewDeleteBucketReplicationRuleDefault(500).WithPayload(err)
}
return user_api.NewDeleteBucketReplicationRuleNoContent()
})
}
func getListRemoteBucketsResponse(session *models.Principal) (*models.ListRemoteBucketsResponse, error) {
@@ -130,7 +171,7 @@ func getAddRemoteBucketResponse(session *models.Principal, params user_api.AddRe
return err
}
adminClient := adminClient{client: mAdmin}
err = addRemoteBucket(ctx, adminClient, *params.Body)
_, err = addRemoteBucket(ctx, adminClient, *params.Body)
if err != nil {
log.Println("error adding remote bucket: ", err)
return err
@@ -184,13 +225,13 @@ func deleteRemoteBucket(ctx context.Context, client MinioAdmin, sourceBucketName
return client.removeRemoteBucket(ctx, sourceBucketName, arn)
}
func addRemoteBucket(ctx context.Context, client MinioAdmin, params models.CreateRemoteBucket) error {
func addRemoteBucket(ctx context.Context, client MinioAdmin, params models.CreateRemoteBucket) (string, error) {
TargetURL := *params.TargetURL
accessKey := *params.AccessKey
secretKey := *params.SecretKey
u, err := url.Parse(TargetURL)
if err != nil {
return errors.New("malformed Remote target URL")
return "", errors.New("malformed Remote target URL")
}
secure := u.Scheme == "https"
host := u.Host
@@ -212,6 +253,225 @@ func addRemoteBucket(ctx context.Context, client MinioAdmin, params models.Creat
Type: "replication",
Region: params.Region,
}
_, err = client.addRemoteBucket(ctx, *params.SourceBucket, remoteBucket)
return err
bucketARN, err := client.addRemoteBucket(ctx, *params.SourceBucket, remoteBucket)
return bucketARN, err
}
func addBucketReplicationItem(ctx context.Context, session *models.Principal, minClient minioClient, bucketName, arn, destinationBucket string) error {
// we will tolerate this call failing
cfg, err := minClient.getBucketReplication(ctx, bucketName)
if err != nil {
log.Println("error versioning bucket:", err)
}
// add rule
maxPrio := 0
for _, r := range cfg.Rules {
if r.Priority > maxPrio {
maxPrio = r.Priority
}
}
maxPrio++
s3Client, err := newS3BucketClient(session, bucketName, "")
if err != nil {
log.Println("error creating S3Client:", err)
return err
}
// create a mc S3Client interface implementation
// defining the client to be used
mcClient := mcClient{client: s3Client}
opts := replication.Options{
RoleArn: arn,
Priority: fmt.Sprintf("%d", maxPrio),
RuleStatus: "enable",
DestBucket: destinationBucket,
Op: replication.AddOption,
}
err2 := mcClient.setReplication(ctx, &cfg, opts)
if err2 != nil {
log.Println("error creating replication for bucket:", err2.Cause)
return err2.Cause
}
return nil
}
func setMultiBucketReplication(ctx context.Context, session *models.Principal, client MinioAdmin, minClient minioClient, params user_api.SetMultiBucketReplicationParams) []RemoteBucketResult {
bucketsRelation := params.Body.BucketsRelation
// Parallel remote bucket adding
parallelRemoteBucket := func(bucketRelationData *models.MultiBucketsRelation) chan RemoteBucketResult {
remoteProc := make(chan RemoteBucketResult)
sourceBucket := bucketRelationData.OriginBucket
targetBucket := bucketRelationData.DestinationBucket
go func() {
defer close(remoteProc)
createRemoteBucketParams := models.CreateRemoteBucket{
AccessKey: params.Body.AccessKey,
SecretKey: params.Body.SecretKey,
SourceBucket: &sourceBucket,
TargetBucket: &targetBucket,
Region: params.Body.Region,
TargetURL: params.Body.TargetURL,
}
// We add the remote bucket reference & store the arn or errors returned
arn, err := addRemoteBucket(ctx, client, createRemoteBucketParams)
if err == nil {
err = addBucketReplicationItem(ctx, session, minClient, sourceBucket, arn, targetBucket)
}
var errorReturn = ""
if err != nil {
errorReturn = err.Error()
}
retParams := RemoteBucketResult{
OriginBucket: sourceBucket,
TargetBucket: targetBucket,
Error: errorReturn,
}
remoteProc <- retParams
}()
return remoteProc
}
var bucketsManagement []chan RemoteBucketResult
for _, bucketName := range bucketsRelation {
// We generate the ARNs for each bucket
rBucket := parallelRemoteBucket(bucketName)
bucketsManagement = append(bucketsManagement, rBucket)
}
resultsList := []RemoteBucketResult{}
for _, result := range bucketsManagement {
res := <-result
resultsList = append(resultsList, res)
}
return resultsList
}
func setMultiBucketReplicationResponse(session *models.Principal, params user_api.SetMultiBucketReplicationParams) (*models.MultiBucketResponseState, *models.Error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, prepareError(err)
}
adminClient := adminClient{client: mAdmin}
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return nil, prepareError(err)
}
// create a minioClient interface implementation
// defining the client to be used
mnClient := minioClient{client: mClient}
replicationResults := setMultiBucketReplication(ctx, session, adminClient, mnClient, params)
if replicationResults == nil {
err = errors.New("error setting buckets replication")
return nil, prepareError(err)
}
resParsed := []*models.MultiBucketResponseItem{}
for _, repResult := range replicationResults {
responseItem := models.MultiBucketResponseItem{
ErrorString: repResult.Error,
OriginBucket: repResult.OriginBucket,
TargetBucket: repResult.TargetBucket,
}
resParsed = append(resParsed, &responseItem)
}
resultsParsed := models.MultiBucketResponseState{
ReplicationState: resParsed,
}
return &resultsParsed, nil
}
func listExternalBucketsResponse(params user_api.ListExternalBucketsParams) (*models.ListBucketsResponse, *models.Error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
remoteAdmin, err := newAdminFromCreds(*params.Body.AccessKey, *params.Body.SecretKey, *params.Body.TargetURL, *params.Body.UseTLS)
if err != nil {
return nil, prepareError(err)
}
// create a minioClient interface implementation
// defining the client to be used
remoteClient := adminClient{client: remoteAdmin}
buckets, err := getAccountInfo(ctx, remoteClient)
if err != nil {
return nil, prepareError(err)
}
// serialize output
listBucketsResponse := &models.ListBucketsResponse{
Buckets: buckets,
Total: int64(len(buckets)),
}
return listBucketsResponse, nil
}
func deleteReplicationRule(ctx context.Context, session *models.Principal, bucketName, ruleID string) error {
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return err
}
// create a minioClient interface implementation
// defining the client to be used
minClient := minioClient{client: mClient}
cfg, err := minClient.getBucketReplication(ctx, bucketName)
if err != nil {
log.Println("error versioning bucket:", err)
}
s3Client, err := newS3BucketClient(session, bucketName, "")
if err != nil {
log.Println("error creating S3Client:", err)
return err
}
// create a mc S3Client interface implementation
// defining the client to be used
mcClient := mcClient{client: s3Client}
opts := replication.Options{
ID: ruleID,
Op: replication.RemoveOption,
}
err2 := mcClient.setReplication(ctx, &cfg, opts)
if err2 != nil {
return err2.Cause
}
return nil
}
func deleteReplicationRuleResponse(session *models.Principal, params user_api.DeleteBucketReplicationRuleParams) *models.Error {
ctx := context.Background()
err := deleteReplicationRule(ctx, session, params.BucketName, params.RuleID)
if err != nil {
return prepareError(err)
}
return nil
}

View File

@@ -319,6 +319,20 @@ func newAdminFromClaims(claims *models.Principal) (*madmin.AdminClient, error) {
return adminClient, nil
}
// newAdminFromCreds Creates a minio client using custom credentials for connecting to a remote host
func newAdminFromCreds(accessKey, secretKey, endpoint string, tlsEnabled bool) (*madmin.AdminClient, error) {
minioClient, err := madmin.NewWithOptions(endpoint, &madmin.Options{
Creds: credentials.NewStaticV4(accessKey, secretKey, ""),
Secure: tlsEnabled,
})
if err != nil {
return nil, err
}
return minioClient, nil
}
// stsClient is a custom http client, this client should not be called directly and instead be
// called using GetConsoleSTSClient() to ensure is initialized and the certificates are loaded correctly
var stsClient *http.Client

View File

@@ -362,6 +362,39 @@ func init() {
}
}
},
"/buckets-replication": {
"post": {
"tags": [
"UserAPI"
],
"summary": "Sets Multi Bucket Replication in multiple Buckets",
"operationId": "SetMultiBucketReplication",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/multiBucketReplication"
}
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/multiBucketResponseState"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/buckets/{bucket_name}/encryption/disable": {
"post": {
"tags": [
@@ -1034,13 +1067,15 @@ func init() {
}
}
}
},
"post": {
}
},
"/buckets/{bucket_name}/replication/{rule_id}": {
"delete": {
"tags": [
"UserAPI"
],
"summary": "Add Bucket Replication",
"operationId": "AddBucketReplication",
"summary": "Bucket Replication Rule Delete",
"operationId": "DeleteBucketReplicationRule",
"parameters": [
{
"type": "string",
@@ -1049,16 +1084,14 @@ func init() {
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/addBucketReplication"
}
"type": "string",
"name": "rule_id",
"in": "path",
"required": true
}
],
"responses": {
"201": {
"204": {
"description": "A successful response."
},
"default": {
@@ -1803,6 +1836,39 @@ func init() {
}
}
},
"/list-external-buckets": {
"post": {
"tags": [
"UserAPI"
],
"summary": "Lists an External list of buckets using custom credentials",
"operationId": "ListExternalBuckets",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/listExternalBucketsParams"
}
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/listBucketsResponse"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/login": {
"get": {
"security": [],
@@ -4363,6 +4429,33 @@ func init() {
}
}
},
"listExternalBucketsParams": {
"required": [
"accessKey",
"secretKey",
"targetURL",
"useTLS"
],
"properties": {
"accessKey": {
"type": "string",
"minLength": 3
},
"region": {
"type": "string"
},
"secretKey": {
"type": "string",
"minLength": 8
},
"targetURL": {
"type": "string"
},
"useTLS": {
"type": "boolean"
}
}
},
"listGroupsResponse": {
"type": "object",
"properties": {
@@ -4589,6 +4682,73 @@ func init() {
}
}
},
"multiBucketReplication": {
"required": [
"accessKey",
"secretKey",
"targetURL",
"bucketsRelation"
],
"properties": {
"accessKey": {
"type": "string",
"minLength": 3
},
"bucketsRelation": {
"type": "array",
"minLength": 1,
"items": {
"$ref": "#/definitions/multiBucketsRelation"
}
},
"region": {
"type": "string"
},
"secretKey": {
"type": "string",
"minLength": 8
},
"targetURL": {
"type": "string"
}
}
},
"multiBucketResponseItem": {
"type": "object",
"properties": {
"errorString": {
"type": "string"
},
"originBucket": {
"type": "string"
},
"targetBucket": {
"type": "string"
}
}
},
"multiBucketResponseState": {
"type": "object",
"properties": {
"replicationState": {
"type": "array",
"items": {
"$ref": "#/definitions/multiBucketResponseItem"
}
}
}
},
"multiBucketsRelation": {
"type": "object",
"properties": {
"destinationBucket": {
"type": "string"
},
"originBucket": {
"type": "string"
}
}
},
"nodeSelectorTerm": {
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
"type": "object",
@@ -6253,6 +6413,39 @@ func init() {
}
}
},
"/buckets-replication": {
"post": {
"tags": [
"UserAPI"
],
"summary": "Sets Multi Bucket Replication in multiple Buckets",
"operationId": "SetMultiBucketReplication",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/multiBucketReplication"
}
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/multiBucketResponseState"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/buckets/{bucket_name}/encryption/disable": {
"post": {
"tags": [
@@ -6925,13 +7118,15 @@ func init() {
}
}
}
},
"post": {
}
},
"/buckets/{bucket_name}/replication/{rule_id}": {
"delete": {
"tags": [
"UserAPI"
],
"summary": "Add Bucket Replication",
"operationId": "AddBucketReplication",
"summary": "Bucket Replication Rule Delete",
"operationId": "DeleteBucketReplicationRule",
"parameters": [
{
"type": "string",
@@ -6940,16 +7135,14 @@ func init() {
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/addBucketReplication"
}
"type": "string",
"name": "rule_id",
"in": "path",
"required": true
}
],
"responses": {
"201": {
"204": {
"description": "A successful response."
},
"default": {
@@ -7694,6 +7887,39 @@ func init() {
}
}
},
"/list-external-buckets": {
"post": {
"tags": [
"UserAPI"
],
"summary": "Lists an External list of buckets using custom credentials",
"operationId": "ListExternalBuckets",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/listExternalBucketsParams"
}
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/listBucketsResponse"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/login": {
"get": {
"security": [],
@@ -10863,6 +11089,33 @@ func init() {
}
}
},
"listExternalBucketsParams": {
"required": [
"accessKey",
"secretKey",
"targetURL",
"useTLS"
],
"properties": {
"accessKey": {
"type": "string",
"minLength": 3
},
"region": {
"type": "string"
},
"secretKey": {
"type": "string",
"minLength": 8
},
"targetURL": {
"type": "string"
},
"useTLS": {
"type": "boolean"
}
}
},
"listGroupsResponse": {
"type": "object",
"properties": {
@@ -11089,6 +11342,73 @@ func init() {
}
}
},
"multiBucketReplication": {
"required": [
"accessKey",
"secretKey",
"targetURL",
"bucketsRelation"
],
"properties": {
"accessKey": {
"type": "string",
"minLength": 3
},
"bucketsRelation": {
"type": "array",
"minLength": 1,
"items": {
"$ref": "#/definitions/multiBucketsRelation"
}
},
"region": {
"type": "string"
},
"secretKey": {
"type": "string",
"minLength": 8
},
"targetURL": {
"type": "string"
}
}
},
"multiBucketResponseItem": {
"type": "object",
"properties": {
"errorString": {
"type": "string"
},
"originBucket": {
"type": "string"
},
"targetBucket": {
"type": "string"
}
}
},
"multiBucketResponseState": {
"type": "object",
"properties": {
"replicationState": {
"type": "array",
"items": {
"$ref": "#/definitions/multiBucketResponseItem"
}
}
}
},
"multiBucketsRelation": {
"type": "object",
"properties": {
"destinationBucket": {
"type": "string"
},
"originBucket": {
"type": "string"
}
}
},
"nodeSelectorTerm": {
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
"type": "object",

View File

@@ -67,9 +67,6 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
UserAPIAccountChangePasswordHandler: user_api.AccountChangePasswordHandlerFunc(func(params user_api.AccountChangePasswordParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.AccountChangePassword has not yet been implemented")
}),
UserAPIAddBucketReplicationHandler: user_api.AddBucketReplicationHandlerFunc(func(params user_api.AddBucketReplicationParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.AddBucketReplication has not yet been implemented")
}),
AdminAPIAddGroupHandler: admin_api.AddGroupHandlerFunc(func(params admin_api.AddGroupParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.AddGroup has not yet been implemented")
}),
@@ -118,6 +115,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
UserAPIDeleteBucketEventHandler: user_api.DeleteBucketEventHandlerFunc(func(params user_api.DeleteBucketEventParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.DeleteBucketEvent has not yet been implemented")
}),
UserAPIDeleteBucketReplicationRuleHandler: user_api.DeleteBucketReplicationRuleHandlerFunc(func(params user_api.DeleteBucketReplicationRuleParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.DeleteBucketReplicationRule has not yet been implemented")
}),
UserAPIDeleteObjectHandler: user_api.DeleteObjectHandlerFunc(func(params user_api.DeleteObjectParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.DeleteObject has not yet been implemented")
}),
@@ -199,6 +199,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
AdminAPIListConfigHandler: admin_api.ListConfigHandlerFunc(func(params admin_api.ListConfigParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListConfig has not yet been implemented")
}),
UserAPIListExternalBucketsHandler: user_api.ListExternalBucketsHandlerFunc(func(params user_api.ListExternalBucketsParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.ListExternalBuckets has not yet been implemented")
}),
AdminAPIListGroupsHandler: admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListGroups has not yet been implemented")
}),
@@ -301,6 +304,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
AdminAPISetConfigHandler: admin_api.SetConfigHandlerFunc(func(params admin_api.SetConfigParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.SetConfig has not yet been implemented")
}),
UserAPISetMultiBucketReplicationHandler: user_api.SetMultiBucketReplicationHandlerFunc(func(params user_api.SetMultiBucketReplicationParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.SetMultiBucketReplication has not yet been implemented")
}),
AdminAPISetPolicyHandler: admin_api.SetPolicyHandlerFunc(func(params admin_api.SetPolicyParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.SetPolicy has not yet been implemented")
}),
@@ -403,8 +409,6 @@ type ConsoleAPI struct {
// UserAPIAccountChangePasswordHandler sets the operation handler for the account change password operation
UserAPIAccountChangePasswordHandler user_api.AccountChangePasswordHandler
// UserAPIAddBucketReplicationHandler sets the operation handler for the add bucket replication operation
UserAPIAddBucketReplicationHandler user_api.AddBucketReplicationHandler
// AdminAPIAddGroupHandler sets the operation handler for the add group operation
AdminAPIAddGroupHandler admin_api.AddGroupHandler
// AdminAPIAddNotificationEndpointHandler sets the operation handler for the add notification endpoint operation
@@ -437,6 +441,8 @@ type ConsoleAPI struct {
UserAPIDeleteBucketHandler user_api.DeleteBucketHandler
// UserAPIDeleteBucketEventHandler sets the operation handler for the delete bucket event operation
UserAPIDeleteBucketEventHandler user_api.DeleteBucketEventHandler
// UserAPIDeleteBucketReplicationRuleHandler sets the operation handler for the delete bucket replication rule operation
UserAPIDeleteBucketReplicationRuleHandler user_api.DeleteBucketReplicationRuleHandler
// UserAPIDeleteObjectHandler sets the operation handler for the delete object operation
UserAPIDeleteObjectHandler user_api.DeleteObjectHandler
// UserAPIDeleteObjectRetentionHandler sets the operation handler for the delete object retention operation
@@ -491,6 +497,8 @@ type ConsoleAPI struct {
UserAPIListBucketsHandler user_api.ListBucketsHandler
// AdminAPIListConfigHandler sets the operation handler for the list config operation
AdminAPIListConfigHandler admin_api.ListConfigHandler
// UserAPIListExternalBucketsHandler sets the operation handler for the list external buckets operation
UserAPIListExternalBucketsHandler user_api.ListExternalBucketsHandler
// AdminAPIListGroupsHandler sets the operation handler for the list groups operation
AdminAPIListGroupsHandler admin_api.ListGroupsHandler
// UserAPIListObjectsHandler sets the operation handler for the list objects operation
@@ -559,6 +567,8 @@ type ConsoleAPI struct {
UserAPISetBucketVersioningHandler user_api.SetBucketVersioningHandler
// AdminAPISetConfigHandler sets the operation handler for the set config operation
AdminAPISetConfigHandler admin_api.SetConfigHandler
// UserAPISetMultiBucketReplicationHandler sets the operation handler for the set multi bucket replication operation
UserAPISetMultiBucketReplicationHandler user_api.SetMultiBucketReplicationHandler
// AdminAPISetPolicyHandler sets the operation handler for the set policy operation
AdminAPISetPolicyHandler admin_api.SetPolicyHandler
// AdminAPISetPolicyMultipleHandler sets the operation handler for the set policy multiple operation
@@ -670,9 +680,6 @@ func (o *ConsoleAPI) Validate() error {
if o.UserAPIAccountChangePasswordHandler == nil {
unregistered = append(unregistered, "user_api.AccountChangePasswordHandler")
}
if o.UserAPIAddBucketReplicationHandler == nil {
unregistered = append(unregistered, "user_api.AddBucketReplicationHandler")
}
if o.AdminAPIAddGroupHandler == nil {
unregistered = append(unregistered, "admin_api.AddGroupHandler")
}
@@ -721,6 +728,9 @@ func (o *ConsoleAPI) Validate() error {
if o.UserAPIDeleteBucketEventHandler == nil {
unregistered = append(unregistered, "user_api.DeleteBucketEventHandler")
}
if o.UserAPIDeleteBucketReplicationRuleHandler == nil {
unregistered = append(unregistered, "user_api.DeleteBucketReplicationRuleHandler")
}
if o.UserAPIDeleteObjectHandler == nil {
unregistered = append(unregistered, "user_api.DeleteObjectHandler")
}
@@ -802,6 +812,9 @@ func (o *ConsoleAPI) Validate() error {
if o.AdminAPIListConfigHandler == nil {
unregistered = append(unregistered, "admin_api.ListConfigHandler")
}
if o.UserAPIListExternalBucketsHandler == nil {
unregistered = append(unregistered, "user_api.ListExternalBucketsHandler")
}
if o.AdminAPIListGroupsHandler == nil {
unregistered = append(unregistered, "admin_api.ListGroupsHandler")
}
@@ -904,6 +917,9 @@ func (o *ConsoleAPI) Validate() error {
if o.AdminAPISetConfigHandler == nil {
unregistered = append(unregistered, "admin_api.SetConfigHandler")
}
if o.UserAPISetMultiBucketReplicationHandler == nil {
unregistered = append(unregistered, "user_api.SetMultiBucketReplicationHandler")
}
if o.AdminAPISetPolicyHandler == nil {
unregistered = append(unregistered, "admin_api.SetPolicyHandler")
}
@@ -1061,10 +1077,6 @@ func (o *ConsoleAPI) initHandlerCache() {
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
o.handlers["POST"]["/buckets/{bucket_name}/replication"] = user_api.NewAddBucketReplication(o.context, o.UserAPIAddBucketReplicationHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
o.handlers["POST"]["/groups"] = admin_api.NewAddGroup(o.context, o.AdminAPIAddGroupHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
@@ -1129,6 +1141,10 @@ func (o *ConsoleAPI) initHandlerCache() {
if o.handlers["DELETE"] == nil {
o.handlers["DELETE"] = make(map[string]http.Handler)
}
o.handlers["DELETE"]["/buckets/{bucket_name}/replication/{rule_id}"] = user_api.NewDeleteBucketReplicationRule(o.context, o.UserAPIDeleteBucketReplicationRuleHandler)
if o.handlers["DELETE"] == nil {
o.handlers["DELETE"] = make(map[string]http.Handler)
}
o.handlers["DELETE"]["/buckets/{bucket_name}/objects"] = user_api.NewDeleteObject(o.context, o.UserAPIDeleteObjectHandler)
if o.handlers["DELETE"] == nil {
o.handlers["DELETE"] = make(map[string]http.Handler)
@@ -1234,6 +1250,10 @@ func (o *ConsoleAPI) initHandlerCache() {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/configs"] = admin_api.NewListConfig(o.context, o.AdminAPIListConfigHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
o.handlers["POST"]["/list-external-buckets"] = user_api.NewListExternalBuckets(o.context, o.UserAPIListExternalBucketsHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
@@ -1370,6 +1390,10 @@ func (o *ConsoleAPI) initHandlerCache() {
o.handlers["PUT"] = make(map[string]http.Handler)
}
o.handlers["PUT"]["/configs/{name}"] = admin_api.NewSetConfig(o.context, o.AdminAPISetConfigHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
o.handlers["POST"]["/buckets-replication"] = user_api.NewSetMultiBucketReplication(o.context, o.UserAPISetMultiBucketReplicationHandler)
if o.handlers["PUT"] == nil {
o.handlers["PUT"] = make(map[string]http.Handler)
}

View File

@@ -1,113 +0,0 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/minio/console/models"
)
// AddBucketReplicationCreatedCode is the HTTP code returned for type AddBucketReplicationCreated
const AddBucketReplicationCreatedCode int = 201
/*AddBucketReplicationCreated A successful response.
swagger:response addBucketReplicationCreated
*/
type AddBucketReplicationCreated struct {
}
// NewAddBucketReplicationCreated creates AddBucketReplicationCreated with default headers values
func NewAddBucketReplicationCreated() *AddBucketReplicationCreated {
return &AddBucketReplicationCreated{}
}
// WriteResponse to the client
func (o *AddBucketReplicationCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(201)
}
/*AddBucketReplicationDefault Generic error response.
swagger:response addBucketReplicationDefault
*/
type AddBucketReplicationDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewAddBucketReplicationDefault creates AddBucketReplicationDefault with default headers values
func NewAddBucketReplicationDefault(code int) *AddBucketReplicationDefault {
if code <= 0 {
code = 500
}
return &AddBucketReplicationDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the add bucket replication default response
func (o *AddBucketReplicationDefault) WithStatusCode(code int) *AddBucketReplicationDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the add bucket replication default response
func (o *AddBucketReplicationDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the add bucket replication default response
func (o *AddBucketReplicationDefault) WithPayload(payload *models.Error) *AddBucketReplicationDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the add bucket replication default response
func (o *AddBucketReplicationDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *AddBucketReplicationDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(o._statusCode)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -0,0 +1,90 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"net/http"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
)
// DeleteBucketReplicationRuleHandlerFunc turns a function with the right signature into a delete bucket replication rule handler
type DeleteBucketReplicationRuleHandlerFunc func(DeleteBucketReplicationRuleParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn DeleteBucketReplicationRuleHandlerFunc) Handle(params DeleteBucketReplicationRuleParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// DeleteBucketReplicationRuleHandler interface for that can handle valid delete bucket replication rule params
type DeleteBucketReplicationRuleHandler interface {
Handle(DeleteBucketReplicationRuleParams, *models.Principal) middleware.Responder
}
// NewDeleteBucketReplicationRule creates a new http.Handler for the delete bucket replication rule operation
func NewDeleteBucketReplicationRule(ctx *middleware.Context, handler DeleteBucketReplicationRuleHandler) *DeleteBucketReplicationRule {
return &DeleteBucketReplicationRule{Context: ctx, Handler: handler}
}
/*DeleteBucketReplicationRule swagger:route DELETE /buckets/{bucket_name}/replication/{rule_id} UserAPI deleteBucketReplicationRule
Bucket Replication Rule Delete
*/
type DeleteBucketReplicationRule struct {
Context *middleware.Context
Handler DeleteBucketReplicationRuleHandler
}
func (o *DeleteBucketReplicationRule) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
}
var Params = NewDeleteBucketReplicationRuleParams()
uprinc, aCtx, err := o.Context.Authorize(r, route)
if err != nil {
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
if aCtx != nil {
r = aCtx
}
var principal *models.Principal
if uprinc != nil {
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
}
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params, principal) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -0,0 +1,114 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
)
// NewDeleteBucketReplicationRuleParams creates a new DeleteBucketReplicationRuleParams object
// no default values defined in spec.
func NewDeleteBucketReplicationRuleParams() DeleteBucketReplicationRuleParams {
return DeleteBucketReplicationRuleParams{}
}
// DeleteBucketReplicationRuleParams contains all the bound params for the delete bucket replication rule operation
// typically these are obtained from a http.Request
//
// swagger:parameters DeleteBucketReplicationRule
type DeleteBucketReplicationRuleParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*
Required: true
In: path
*/
BucketName string
/*
Required: true
In: path
*/
RuleID string
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewDeleteBucketReplicationRuleParams() beforehand.
func (o *DeleteBucketReplicationRuleParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name")
if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil {
res = append(res, err)
}
rRuleID, rhkRuleID, _ := route.Params.GetOK("rule_id")
if err := o.bindRuleID(rRuleID, rhkRuleID, route.Formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// bindBucketName binds and validates parameter BucketName from path.
func (o *DeleteBucketReplicationRuleParams) bindBucketName(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
// Parameter is provided by construction from the route
o.BucketName = raw
return nil
}
// bindRuleID binds and validates parameter RuleID from path.
func (o *DeleteBucketReplicationRuleParams) bindRuleID(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
// Parameter is provided by construction from the route
o.RuleID = raw
return nil
}

View File

@@ -0,0 +1,113 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/minio/console/models"
)
// DeleteBucketReplicationRuleNoContentCode is the HTTP code returned for type DeleteBucketReplicationRuleNoContent
const DeleteBucketReplicationRuleNoContentCode int = 204
/*DeleteBucketReplicationRuleNoContent A successful response.
swagger:response deleteBucketReplicationRuleNoContent
*/
type DeleteBucketReplicationRuleNoContent struct {
}
// NewDeleteBucketReplicationRuleNoContent creates DeleteBucketReplicationRuleNoContent with default headers values
func NewDeleteBucketReplicationRuleNoContent() *DeleteBucketReplicationRuleNoContent {
return &DeleteBucketReplicationRuleNoContent{}
}
// WriteResponse to the client
func (o *DeleteBucketReplicationRuleNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(204)
}
/*DeleteBucketReplicationRuleDefault Generic error response.
swagger:response deleteBucketReplicationRuleDefault
*/
type DeleteBucketReplicationRuleDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewDeleteBucketReplicationRuleDefault creates DeleteBucketReplicationRuleDefault with default headers values
func NewDeleteBucketReplicationRuleDefault(code int) *DeleteBucketReplicationRuleDefault {
if code <= 0 {
code = 500
}
return &DeleteBucketReplicationRuleDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the delete bucket replication rule default response
func (o *DeleteBucketReplicationRuleDefault) WithStatusCode(code int) *DeleteBucketReplicationRuleDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the delete bucket replication rule default response
func (o *DeleteBucketReplicationRuleDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the delete bucket replication rule default response
func (o *DeleteBucketReplicationRuleDefault) WithPayload(payload *models.Error) *DeleteBucketReplicationRuleDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the delete bucket replication rule default response
func (o *DeleteBucketReplicationRuleDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *DeleteBucketReplicationRuleDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(o._statusCode)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -0,0 +1,124 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"errors"
"net/url"
golangswaggerpaths "path"
"strings"
)
// DeleteBucketReplicationRuleURL generates an URL for the delete bucket replication rule operation
type DeleteBucketReplicationRuleURL struct {
BucketName string
RuleID string
_basePath string
// avoid unkeyed usage
_ struct{}
}
// WithBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *DeleteBucketReplicationRuleURL) WithBasePath(bp string) *DeleteBucketReplicationRuleURL {
o.SetBasePath(bp)
return o
}
// SetBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *DeleteBucketReplicationRuleURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *DeleteBucketReplicationRuleURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/buckets/{bucket_name}/replication/{rule_id}"
bucketName := o.BucketName
if bucketName != "" {
_path = strings.Replace(_path, "{bucket_name}", bucketName, -1)
} else {
return nil, errors.New("bucketName is required on DeleteBucketReplicationRuleURL")
}
ruleID := o.RuleID
if ruleID != "" {
_path = strings.Replace(_path, "{rule_id}", ruleID, -1)
} else {
return nil, errors.New("ruleId is required on DeleteBucketReplicationRuleURL")
}
_basePath := o._basePath
if _basePath == "" {
_basePath = "/api/v1"
}
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error
func (o *DeleteBucketReplicationRuleURL) Must(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
if u == nil {
panic("url can't be nil")
}
return u
}
// String returns the string representation of the path with query string
func (o *DeleteBucketReplicationRuleURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *DeleteBucketReplicationRuleURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on DeleteBucketReplicationRuleURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on DeleteBucketReplicationRuleURL")
}
base, err := o.Build()
if err != nil {
return nil, err
}
base.Scheme = scheme
base.Host = host
return base, nil
}
// StringFull returns the string representation of a complete url
func (o *DeleteBucketReplicationRuleURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -30,40 +30,40 @@ import (
"github.com/minio/console/models"
)
// AddBucketReplicationHandlerFunc turns a function with the right signature into a add bucket replication handler
type AddBucketReplicationHandlerFunc func(AddBucketReplicationParams, *models.Principal) middleware.Responder
// ListExternalBucketsHandlerFunc turns a function with the right signature into a list external buckets handler
type ListExternalBucketsHandlerFunc func(ListExternalBucketsParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn AddBucketReplicationHandlerFunc) Handle(params AddBucketReplicationParams, principal *models.Principal) middleware.Responder {
func (fn ListExternalBucketsHandlerFunc) Handle(params ListExternalBucketsParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// AddBucketReplicationHandler interface for that can handle valid add bucket replication params
type AddBucketReplicationHandler interface {
Handle(AddBucketReplicationParams, *models.Principal) middleware.Responder
// ListExternalBucketsHandler interface for that can handle valid list external buckets params
type ListExternalBucketsHandler interface {
Handle(ListExternalBucketsParams, *models.Principal) middleware.Responder
}
// NewAddBucketReplication creates a new http.Handler for the add bucket replication operation
func NewAddBucketReplication(ctx *middleware.Context, handler AddBucketReplicationHandler) *AddBucketReplication {
return &AddBucketReplication{Context: ctx, Handler: handler}
// NewListExternalBuckets creates a new http.Handler for the list external buckets operation
func NewListExternalBuckets(ctx *middleware.Context, handler ListExternalBucketsHandler) *ListExternalBuckets {
return &ListExternalBuckets{Context: ctx, Handler: handler}
}
/*AddBucketReplication swagger:route POST /buckets/{bucket_name}/replication UserAPI addBucketReplication
/*ListExternalBuckets swagger:route POST /list-external-buckets UserAPI listExternalBuckets
Add Bucket Replication
Lists an External list of buckets using custom credentials
*/
type AddBucketReplication struct {
type ListExternalBuckets struct {
Context *middleware.Context
Handler AddBucketReplicationHandler
Handler ListExternalBucketsHandler
}
func (o *AddBucketReplication) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
func (o *ListExternalBuckets) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
}
var Params = NewAddBucketReplicationParams()
var Params = NewListExternalBucketsParams()
uprinc, aCtx, err := o.Context.Authorize(r, route)
if err != nil {

View File

@@ -29,23 +29,22 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/minio/console/models"
)
// NewAddBucketReplicationParams creates a new AddBucketReplicationParams object
// NewListExternalBucketsParams creates a new ListExternalBucketsParams object
// no default values defined in spec.
func NewAddBucketReplicationParams() AddBucketReplicationParams {
func NewListExternalBucketsParams() ListExternalBucketsParams {
return AddBucketReplicationParams{}
return ListExternalBucketsParams{}
}
// AddBucketReplicationParams contains all the bound params for the add bucket replication operation
// ListExternalBucketsParams contains all the bound params for the list external buckets operation
// typically these are obtained from a http.Request
//
// swagger:parameters AddBucketReplication
type AddBucketReplicationParams struct {
// swagger:parameters ListExternalBuckets
type ListExternalBucketsParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
@@ -54,26 +53,21 @@ type AddBucketReplicationParams struct {
Required: true
In: body
*/
Body *models.AddBucketReplication
/*
Required: true
In: path
*/
BucketName string
Body *models.ListExternalBucketsParams
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewAddBucketReplicationParams() beforehand.
func (o *AddBucketReplicationParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
// To ensure default values, the struct must have been initialized with NewListExternalBucketsParams() beforehand.
func (o *ListExternalBucketsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
if runtime.HasBody(r) {
defer r.Body.Close()
var body models.AddBucketReplication
var body models.ListExternalBucketsParams
if err := route.Consumer.Consume(r.Body, &body); err != nil {
if err == io.EOF {
res = append(res, errors.Required("body", "body", ""))
@@ -93,28 +87,8 @@ func (o *AddBucketReplicationParams) BindRequest(r *http.Request, route *middlew
} else {
res = append(res, errors.Required("body", "body", ""))
}
rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name")
if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// bindBucketName binds and validates parameter BucketName from path.
func (o *AddBucketReplicationParams) bindBucketName(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
// Parameter is provided by construction from the route
o.BucketName = raw
return nil
}

View File

@@ -0,0 +1,133 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/minio/console/models"
)
// ListExternalBucketsOKCode is the HTTP code returned for type ListExternalBucketsOK
const ListExternalBucketsOKCode int = 200
/*ListExternalBucketsOK A successful response.
swagger:response listExternalBucketsOK
*/
type ListExternalBucketsOK struct {
/*
In: Body
*/
Payload *models.ListBucketsResponse `json:"body,omitempty"`
}
// NewListExternalBucketsOK creates ListExternalBucketsOK with default headers values
func NewListExternalBucketsOK() *ListExternalBucketsOK {
return &ListExternalBucketsOK{}
}
// WithPayload adds the payload to the list external buckets o k response
func (o *ListExternalBucketsOK) WithPayload(payload *models.ListBucketsResponse) *ListExternalBucketsOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list external buckets o k response
func (o *ListExternalBucketsOK) SetPayload(payload *models.ListBucketsResponse) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListExternalBucketsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(200)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}
/*ListExternalBucketsDefault Generic error response.
swagger:response listExternalBucketsDefault
*/
type ListExternalBucketsDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewListExternalBucketsDefault creates ListExternalBucketsDefault with default headers values
func NewListExternalBucketsDefault(code int) *ListExternalBucketsDefault {
if code <= 0 {
code = 500
}
return &ListExternalBucketsDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the list external buckets default response
func (o *ListExternalBucketsDefault) WithStatusCode(code int) *ListExternalBucketsDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the list external buckets default response
func (o *ListExternalBucketsDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the list external buckets default response
func (o *ListExternalBucketsDefault) WithPayload(payload *models.Error) *ListExternalBucketsDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list external buckets default response
func (o *ListExternalBucketsDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListExternalBucketsDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(o._statusCode)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -26,22 +26,17 @@ import (
"errors"
"net/url"
golangswaggerpaths "path"
"strings"
)
// AddBucketReplicationURL generates an URL for the add bucket replication operation
type AddBucketReplicationURL struct {
BucketName string
// ListExternalBucketsURL generates an URL for the list external buckets operation
type ListExternalBucketsURL struct {
_basePath string
// avoid unkeyed usage
_ struct{}
}
// WithBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *AddBucketReplicationURL) WithBasePath(bp string) *AddBucketReplicationURL {
func (o *ListExternalBucketsURL) WithBasePath(bp string) *ListExternalBucketsURL {
o.SetBasePath(bp)
return o
}
@@ -49,22 +44,15 @@ func (o *AddBucketReplicationURL) WithBasePath(bp string) *AddBucketReplicationU
// SetBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *AddBucketReplicationURL) SetBasePath(bp string) {
func (o *ListExternalBucketsURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *AddBucketReplicationURL) Build() (*url.URL, error) {
func (o *ListExternalBucketsURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/buckets/{bucket_name}/replication"
bucketName := o.BucketName
if bucketName != "" {
_path = strings.Replace(_path, "{bucket_name}", bucketName, -1)
} else {
return nil, errors.New("bucketName is required on AddBucketReplicationURL")
}
var _path = "/list-external-buckets"
_basePath := o._basePath
if _basePath == "" {
@@ -76,7 +64,7 @@ func (o *AddBucketReplicationURL) Build() (*url.URL, error) {
}
// Must is a helper function to panic when the url builder returns an error
func (o *AddBucketReplicationURL) Must(u *url.URL, err error) *url.URL {
func (o *ListExternalBucketsURL) Must(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
@@ -87,17 +75,17 @@ func (o *AddBucketReplicationURL) Must(u *url.URL, err error) *url.URL {
}
// String returns the string representation of the path with query string
func (o *AddBucketReplicationURL) String() string {
func (o *ListExternalBucketsURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *AddBucketReplicationURL) BuildFull(scheme, host string) (*url.URL, error) {
func (o *ListExternalBucketsURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on AddBucketReplicationURL")
return nil, errors.New("scheme is required for a full url on ListExternalBucketsURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on AddBucketReplicationURL")
return nil, errors.New("host is required for a full url on ListExternalBucketsURL")
}
base, err := o.Build()
@@ -111,6 +99,6 @@ func (o *AddBucketReplicationURL) BuildFull(scheme, host string) (*url.URL, erro
}
// StringFull returns the string representation of a complete url
func (o *AddBucketReplicationURL) StringFull(scheme, host string) string {
func (o *ListExternalBucketsURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -0,0 +1,90 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"net/http"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
)
// SetMultiBucketReplicationHandlerFunc turns a function with the right signature into a set multi bucket replication handler
type SetMultiBucketReplicationHandlerFunc func(SetMultiBucketReplicationParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn SetMultiBucketReplicationHandlerFunc) Handle(params SetMultiBucketReplicationParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// SetMultiBucketReplicationHandler interface for that can handle valid set multi bucket replication params
type SetMultiBucketReplicationHandler interface {
Handle(SetMultiBucketReplicationParams, *models.Principal) middleware.Responder
}
// NewSetMultiBucketReplication creates a new http.Handler for the set multi bucket replication operation
func NewSetMultiBucketReplication(ctx *middleware.Context, handler SetMultiBucketReplicationHandler) *SetMultiBucketReplication {
return &SetMultiBucketReplication{Context: ctx, Handler: handler}
}
/*SetMultiBucketReplication swagger:route POST /buckets-replication UserAPI setMultiBucketReplication
Sets Multi Bucket Replication in multiple Buckets
*/
type SetMultiBucketReplication struct {
Context *middleware.Context
Handler SetMultiBucketReplicationHandler
}
func (o *SetMultiBucketReplication) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
}
var Params = NewSetMultiBucketReplicationParams()
uprinc, aCtx, err := o.Context.Authorize(r, route)
if err != nil {
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
if aCtx != nil {
r = aCtx
}
var principal *models.Principal
if uprinc != nil {
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
}
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params, principal) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -0,0 +1,94 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"io"
"net/http"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
)
// NewSetMultiBucketReplicationParams creates a new SetMultiBucketReplicationParams object
// no default values defined in spec.
func NewSetMultiBucketReplicationParams() SetMultiBucketReplicationParams {
return SetMultiBucketReplicationParams{}
}
// SetMultiBucketReplicationParams contains all the bound params for the set multi bucket replication operation
// typically these are obtained from a http.Request
//
// swagger:parameters SetMultiBucketReplication
type SetMultiBucketReplicationParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*
Required: true
In: body
*/
Body *models.MultiBucketReplication
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewSetMultiBucketReplicationParams() beforehand.
func (o *SetMultiBucketReplicationParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
if runtime.HasBody(r) {
defer r.Body.Close()
var body models.MultiBucketReplication
if err := route.Consumer.Consume(r.Body, &body); err != nil {
if err == io.EOF {
res = append(res, errors.Required("body", "body", ""))
} else {
res = append(res, errors.NewParseError("body", "body", "", err))
}
} else {
// validate body object
if err := body.Validate(route.Formats); err != nil {
res = append(res, err)
}
if len(res) == 0 {
o.Body = &body
}
}
} else {
res = append(res, errors.Required("body", "body", ""))
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,133 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/minio/console/models"
)
// SetMultiBucketReplicationOKCode is the HTTP code returned for type SetMultiBucketReplicationOK
const SetMultiBucketReplicationOKCode int = 200
/*SetMultiBucketReplicationOK A successful response.
swagger:response setMultiBucketReplicationOK
*/
type SetMultiBucketReplicationOK struct {
/*
In: Body
*/
Payload *models.MultiBucketResponseState `json:"body,omitempty"`
}
// NewSetMultiBucketReplicationOK creates SetMultiBucketReplicationOK with default headers values
func NewSetMultiBucketReplicationOK() *SetMultiBucketReplicationOK {
return &SetMultiBucketReplicationOK{}
}
// WithPayload adds the payload to the set multi bucket replication o k response
func (o *SetMultiBucketReplicationOK) WithPayload(payload *models.MultiBucketResponseState) *SetMultiBucketReplicationOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the set multi bucket replication o k response
func (o *SetMultiBucketReplicationOK) SetPayload(payload *models.MultiBucketResponseState) {
o.Payload = payload
}
// WriteResponse to the client
func (o *SetMultiBucketReplicationOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(200)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}
/*SetMultiBucketReplicationDefault Generic error response.
swagger:response setMultiBucketReplicationDefault
*/
type SetMultiBucketReplicationDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewSetMultiBucketReplicationDefault creates SetMultiBucketReplicationDefault with default headers values
func NewSetMultiBucketReplicationDefault(code int) *SetMultiBucketReplicationDefault {
if code <= 0 {
code = 500
}
return &SetMultiBucketReplicationDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the set multi bucket replication default response
func (o *SetMultiBucketReplicationDefault) WithStatusCode(code int) *SetMultiBucketReplicationDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the set multi bucket replication default response
func (o *SetMultiBucketReplicationDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the set multi bucket replication default response
func (o *SetMultiBucketReplicationDefault) WithPayload(payload *models.Error) *SetMultiBucketReplicationDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the set multi bucket replication default response
func (o *SetMultiBucketReplicationDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *SetMultiBucketReplicationDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(o._statusCode)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -0,0 +1,104 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// 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/>.
//
package user_api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"errors"
"net/url"
golangswaggerpaths "path"
)
// SetMultiBucketReplicationURL generates an URL for the set multi bucket replication operation
type SetMultiBucketReplicationURL struct {
_basePath string
}
// WithBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *SetMultiBucketReplicationURL) WithBasePath(bp string) *SetMultiBucketReplicationURL {
o.SetBasePath(bp)
return o
}
// SetBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *SetMultiBucketReplicationURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *SetMultiBucketReplicationURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/buckets-replication"
_basePath := o._basePath
if _basePath == "" {
_basePath = "/api/v1"
}
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error
func (o *SetMultiBucketReplicationURL) Must(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
if u == nil {
panic("url can't be nil")
}
return u
}
// String returns the string representation of the path with query string
func (o *SetMultiBucketReplicationURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *SetMultiBucketReplicationURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on SetMultiBucketReplicationURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on SetMultiBucketReplicationURL")
}
base, err := o.Build()
if err != nil {
return nil, err
}
base.Scheme = scheme
base.Host = host
return base, nil
}
// StringFull returns the string representation of a complete url
func (o *SetMultiBucketReplicationURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -26,7 +26,6 @@ import (
"github.com/minio/mc/pkg/probe"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/replication"
"github.com/minio/minio-go/v7/pkg/sse"
"errors"
@@ -105,14 +104,6 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) {
}
return user_api.NewGetBucketReplicationOK().WithPayload(getBucketReplication)
})
// get bucket replication
api.UserAPIAddBucketReplicationHandler = user_api.AddBucketReplicationHandlerFunc(func(params user_api.AddBucketReplicationParams, session *models.Principal) middleware.Responder {
err := getAddBucketReplicationdResponse(session, params.BucketName, &params)
if err != nil {
return user_api.NewAddBucketReplicationDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewAddBucketReplicationCreated()
})
// enable bucket encryption
api.UserAPIEnableBucketEncryptionHandler = user_api.EnableBucketEncryptionHandlerFunc(func(params user_api.EnableBucketEncryptionParams, session *models.Principal) middleware.Responder {
if err := enableBucketEncryptionResponse(session, params); err != nil {
@@ -160,61 +151,6 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) {
})
}
func getAddBucketReplicationdResponse(session *models.Principal, bucketName string, params *user_api.AddBucketReplicationParams) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return err
}
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
// we will tolerate this call failing
cfg, err := minioClient.getBucketReplication(ctx, bucketName)
if err != nil {
log.Println("error versioning bucket:", err)
}
// add rule
maxPrio := 0
for _, r := range cfg.Rules {
if r.Priority > maxPrio {
maxPrio = r.Priority
}
}
maxPrio++
s3Client, err := newS3BucketClient(session, bucketName, "")
if err != nil {
log.Println("error creating S3Client:", err)
return err
}
// create a mc S3Client interface implementation
// defining the client to be used
mcClient := mcClient{client: s3Client}
opts := replication.Options{
RoleArn: params.Body.Arn,
Priority: fmt.Sprintf("%d", maxPrio),
RuleStatus: "enable",
//ID: cliCtx.String("id"),
DestBucket: params.Body.DestinationBucket,
Op: replication.AddOption,
}
err2 := mcClient.setReplication(ctx, &cfg, opts)
if err2 != nil {
log.Println("error creating replication for bucket:", err2.Cause)
return err2.Cause
}
return nil
}
type VersionState string
const (

View File

@@ -709,6 +709,51 @@ paths:
$ref: "#/definitions/error"
tags:
- UserAPI
/list-external-buckets:
post:
summary: Lists an External list of buckets using custom credentials
operationId: ListExternalBuckets
parameters:
- name: body
in: body
required: true
schema:
$ref: "#/definitions/listExternalBucketsParams"
responses:
200:
description: A successful response.
schema:
$ref: "#/definitions/listBucketsResponse"
default:
description: Generic error response.
schema:
$ref: "#/definitions/error"
tags:
- UserAPI
/buckets-replication:
post:
summary: Sets Multi Bucket Replication in multiple Buckets
operationId: SetMultiBucketReplication
parameters:
- name: body
in: body
required: true
schema:
$ref: "#/definitions/multiBucketReplication"
responses:
200:
description: A successful response.
schema:
$ref: "#/definitions/multiBucketResponseState"
default:
description: Generic error response.
schema:
$ref: "#/definitions/error"
tags:
- UserAPI
/buckets/{bucket_name}/replication:
get:
@@ -730,21 +775,22 @@ paths:
$ref: "#/definitions/error"
tags:
- UserAPI
post:
summary: Add Bucket Replication
operationId: AddBucketReplication
/buckets/{bucket_name}/replication/{rule_id}:
delete:
summary: Bucket Replication Rule Delete
operationId: DeleteBucketReplicationRule
parameters:
- name: bucket_name
in: path
required: true
type: string
- name: body
in: body
- name: rule_id
in: path
required: true
schema:
$ref: "#/definitions/addBucketReplication"
type: string
responses:
201:
204:
description: A successful response.
default:
description: Generic error response.
@@ -752,6 +798,7 @@ paths:
$ref: "#/definitions/error"
tags:
- UserAPI
/buckets/{bucket_name}/versioning:
get:
summary: Bucket Versioning
@@ -2691,6 +2738,76 @@ definitions:
# }
# }
#}
listExternalBucketsParams:
required:
- accessKey
- secretKey
- targetURL
- useTLS
properties:
accessKey:
type: string
minLength: 3
secretKey:
type: string
minLength: 8
targetURL:
type: string
useTLS:
type: boolean
region:
type: string
multiBucketReplication:
required:
- accessKey
- secretKey
- targetURL
- bucketsRelation
properties:
accessKey:
type: string
minLength: 3
secretKey:
type: string
minLength: 8
targetURL:
type: string
region:
type: string
bucketsRelation:
type: array
minLength: 1
items:
$ref: "#/definitions/multiBucketsRelation"
multiBucketsRelation:
type: object
properties:
originBucket:
type: string
destinationBucket:
type: string
multiBucketResponseItem:
type: object
properties:
originBucket:
type: string
targetBucket:
type: string
errorString:
type: string
multiBucketResponseState:
type: object
properties:
replicationState:
type: array
items:
$ref: "#/definitions/multiBucketResponseItem"
addBucketReplication:
type: object
properties: