Enable Bucket Quota on Bucket Details (#776)
* Enable Bucket Quota on Bucket Details Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> * warnings Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> * remove uselss br Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
120
models/bucket_quota.go
Normal file
120
models/bucket_quota.go
Normal file
@@ -0,0 +1,120 @@
|
||||
// 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 (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// BucketQuota bucket quota
|
||||
//
|
||||
// swagger:model bucketQuota
|
||||
type BucketQuota struct {
|
||||
|
||||
// quota
|
||||
Quota int64 `json:"quota,omitempty"`
|
||||
|
||||
// type
|
||||
// Enum: [hard fifo]
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this bucket quota
|
||||
func (m *BucketQuota) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateType(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var bucketQuotaTypeTypePropEnum []interface{}
|
||||
|
||||
func init() {
|
||||
var res []string
|
||||
if err := json.Unmarshal([]byte(`["hard","fifo"]`), &res); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, v := range res {
|
||||
bucketQuotaTypeTypePropEnum = append(bucketQuotaTypeTypePropEnum, v)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
// BucketQuotaTypeHard captures enum value "hard"
|
||||
BucketQuotaTypeHard string = "hard"
|
||||
|
||||
// BucketQuotaTypeFifo captures enum value "fifo"
|
||||
BucketQuotaTypeFifo string = "fifo"
|
||||
)
|
||||
|
||||
// prop value enum
|
||||
func (m *BucketQuota) validateTypeEnum(path, location string, value string) error {
|
||||
if err := validate.EnumCase(path, location, value, bucketQuotaTypeTypePropEnum, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BucketQuota) validateType(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Type) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
// value enum
|
||||
if err := m.validateTypeEnum("type", "body", m.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *BucketQuota) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *BucketQuota) UnmarshalBinary(b []byte) error {
|
||||
var res BucketQuota
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
BucketEncryptionInfo,
|
||||
BucketInfo,
|
||||
BucketObjectLocking,
|
||||
BucketQuota,
|
||||
BucketReplication,
|
||||
BucketVersioning,
|
||||
} from "../types";
|
||||
@@ -43,6 +44,8 @@ import SetRetentionConfig from "./SetRetentionConfig";
|
||||
import EnableBucketEncryption from "./EnableBucketEncryption";
|
||||
import EnableVersioningModal from "./EnableVersioningModal";
|
||||
import UsageIcon from "../../../../icons/UsageIcon";
|
||||
import GavelIcon from "@material-ui/icons/Gavel";
|
||||
import EnableQuota from "./EnableQuota";
|
||||
|
||||
interface IBucketSummaryProps {
|
||||
classes: any;
|
||||
@@ -71,6 +74,12 @@ const styles = (theme: Theme) =>
|
||||
reportedUsage: {
|
||||
padding: "15px",
|
||||
},
|
||||
dualCardLeft: {
|
||||
paddingRight: "5px",
|
||||
},
|
||||
dualCardRight: {
|
||||
paddingLeft: "5px",
|
||||
},
|
||||
...hrClass,
|
||||
...buttonsStyles,
|
||||
});
|
||||
@@ -93,13 +102,18 @@ const BucketSummary = ({
|
||||
const [loadingBucket, setLoadingBucket] = useState<boolean>(true);
|
||||
const [loadingEncryption, setLoadingEncryption] = useState<boolean>(true);
|
||||
const [loadingVersioning, setLoadingVersioning] = useState<boolean>(true);
|
||||
const [loadingQuota, setLoadingQuota] = useState<boolean>(true);
|
||||
const [loadingReplication, setLoadingReplication] = useState<boolean>(true);
|
||||
const [isVersioned, setIsVersioned] = useState<boolean>(false);
|
||||
const [quotaEnabled, setQuotaEnabled] = useState<boolean>(false);
|
||||
const [quota, setQuota] = useState<BucketQuota | null>(null);
|
||||
const [encryptionEnabled, setEncryptionEnabled] = useState<boolean>(false);
|
||||
const [retentionConfigOpen, setRetentionConfigOpen] =
|
||||
useState<boolean>(false);
|
||||
const [enableEncryptionScreenOpen, setEnableEncryptionScreenOpen] =
|
||||
useState<boolean>(false);
|
||||
const [enableQuotaScreenOpen, setEnableQuotaScreenOpen] =
|
||||
useState<boolean>(false);
|
||||
const [enableVersioningOpen, setEnableVersioningOpen] =
|
||||
useState<boolean>(false);
|
||||
|
||||
@@ -166,6 +180,27 @@ const BucketSummary = ({
|
||||
}
|
||||
}, [loadingVersioning, setErrorSnackMessage, bucketName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loadingQuota) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets/${bucketName}/quota`)
|
||||
.then((res: BucketQuota) => {
|
||||
setQuota(res);
|
||||
if (res.quota) {
|
||||
setQuotaEnabled(true);
|
||||
} else {
|
||||
setQuotaEnabled(false);
|
||||
}
|
||||
setLoadingQuota(false);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
setErrorSnackMessage(err);
|
||||
setQuotaEnabled(false);
|
||||
setLoadingVersioning(false);
|
||||
});
|
||||
}
|
||||
}, [loadingQuota, setLoadingVersioning, setErrorSnackMessage, bucketName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loadingVersioning) {
|
||||
api
|
||||
@@ -234,10 +269,17 @@ const BucketSummary = ({
|
||||
const setBucketVersioning = () => {
|
||||
setEnableVersioningOpen(true);
|
||||
};
|
||||
const setBucketQuota = () => {
|
||||
setEnableQuotaScreenOpen(true);
|
||||
};
|
||||
|
||||
const closeEnableBucketEncryption = () => {
|
||||
setEnableEncryptionScreenOpen(false);
|
||||
loadAllBucketData();
|
||||
setLoadingEncryption(true);
|
||||
};
|
||||
const closeEnableBucketQuota = () => {
|
||||
setEnableQuotaScreenOpen(false);
|
||||
setLoadingQuota(true);
|
||||
};
|
||||
|
||||
const closeSetAccessPolicy = () => {
|
||||
@@ -257,6 +299,13 @@ const BucketSummary = ({
|
||||
}
|
||||
};
|
||||
|
||||
const cap = (str: string) => {
|
||||
if (!str) {
|
||||
return null;
|
||||
}
|
||||
return str[0].toUpperCase() + str.slice(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{enableEncryptionScreenOpen && (
|
||||
@@ -268,6 +317,15 @@ const BucketSummary = ({
|
||||
closeModalAndRefresh={closeEnableBucketEncryption}
|
||||
/>
|
||||
)}
|
||||
{enableQuotaScreenOpen && (
|
||||
<EnableQuota
|
||||
open={enableQuotaScreenOpen}
|
||||
selectedBucket={bucketName}
|
||||
enabled={quotaEnabled}
|
||||
cfg={quota}
|
||||
closeModalAndRefresh={closeEnableBucketQuota}
|
||||
/>
|
||||
)}
|
||||
{accessPolicyScreenOpen && (
|
||||
<SetAccessPolicy
|
||||
bucketName={bucketName}
|
||||
@@ -381,10 +439,10 @@ const BucketSummary = ({
|
||||
<br />
|
||||
<Paper className={classes.paperContainer}>
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<Grid item xs={quotaEnabled ? 9 : 12}>
|
||||
<h2>Versioning</h2>
|
||||
<hr className={classes.hrClass} />
|
||||
<table>
|
||||
<table width={"100%"}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className={classes.titleCol}>Versioning:</td>
|
||||
@@ -407,10 +465,47 @@ const BucketSummary = ({
|
||||
</Fragment>
|
||||
)}
|
||||
</td>
|
||||
<td className={classes.titleCol}>Quota:</td>
|
||||
<td>
|
||||
{loadingQuota ? (
|
||||
<CircularProgress
|
||||
color="primary"
|
||||
size={16}
|
||||
variant="indeterminate"
|
||||
/>
|
||||
) : (
|
||||
<Fragment>
|
||||
<Button
|
||||
color="primary"
|
||||
className={classes.anchorButton}
|
||||
onClick={setBucketQuota}
|
||||
>
|
||||
{quotaEnabled ? "Enabled" : "Disabled"}
|
||||
</Button>
|
||||
</Fragment>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</Grid>
|
||||
{quotaEnabled && quota && (
|
||||
<Grid item xs={3} className={classes.reportedUsage}>
|
||||
<Grid container direction="row" alignItems="center">
|
||||
<Grid item className={classes.icon} xs={2}>
|
||||
<GavelIcon />
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
<Typography className={classes.elementTitle}>
|
||||
{cap(quota?.type)} Quota
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Typography className={classes.consumptionValue}>
|
||||
{niceBytes(`${quota?.quota}`)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Paper>
|
||||
<br />
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
// 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, { useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import { Button, LinearProgress } from "@material-ui/core";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import RadioGroupSelector from "../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
|
||||
import { factorForDropdown, getBytes, units } from "../../../../common/utils";
|
||||
import { BucketQuota } from "../types";
|
||||
import { setModalErrorSnackMessage } from "../../../../actions";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
|
||||
import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
|
||||
import api from "../../../../common/api";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
minTableHeader: {
|
||||
color: "#393939",
|
||||
"& tr": {
|
||||
"& th": {
|
||||
fontWeight: "bold",
|
||||
},
|
||||
},
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const,
|
||||
},
|
||||
...modalBasic,
|
||||
});
|
||||
|
||||
interface IEnableQuotaProps {
|
||||
classes: any;
|
||||
open: boolean;
|
||||
enabled: boolean;
|
||||
cfg: BucketQuota | null;
|
||||
selectedBucket: string;
|
||||
closeModalAndRefresh: () => void;
|
||||
setModalErrorSnackMessage: typeof setModalErrorSnackMessage;
|
||||
}
|
||||
|
||||
const EnableQuota = ({
|
||||
classes,
|
||||
open,
|
||||
enabled,
|
||||
cfg,
|
||||
selectedBucket,
|
||||
closeModalAndRefresh,
|
||||
setModalErrorSnackMessage,
|
||||
}: IEnableQuotaProps) => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [quotaEnabled, setQuotaEnabled] = useState<boolean>(false);
|
||||
const [quotaType, setQuotaType] = useState<string>("hard");
|
||||
const [quotaSize, setQuotaSize] = useState<string>("1");
|
||||
const [quotaUnit, setQuotaUnit] = useState<string>("TiB");
|
||||
|
||||
useEffect(() => {
|
||||
if (enabled) {
|
||||
setQuotaEnabled(true);
|
||||
if (cfg) {
|
||||
setQuotaType(cfg.type);
|
||||
setQuotaSize(`${cfg.quota}`);
|
||||
setQuotaUnit(`B`);
|
||||
|
||||
let maxUnit = "B";
|
||||
let maxQuota = cfg.quota;
|
||||
|
||||
for (let i = 0; i < units.length; i++) {
|
||||
if (cfg.quota % Math.pow(1024, i) === 0) {
|
||||
maxQuota = cfg.quota / Math.pow(1024, i);
|
||||
maxUnit = units[i];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
setQuotaSize(`${maxQuota}`);
|
||||
setQuotaUnit(maxUnit);
|
||||
}
|
||||
}
|
||||
}, [enabled, cfg]);
|
||||
|
||||
const enableBucketEncryption = (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
let req = {
|
||||
enabled: quotaEnabled,
|
||||
amount: parseInt(getBytes(quotaSize, quotaUnit, false)),
|
||||
quota_type: quotaType,
|
||||
};
|
||||
|
||||
api
|
||||
.invoke("PUT", `/api/v1/buckets/${selectedBucket}/quota`, req)
|
||||
.then(() => {
|
||||
setLoading(false);
|
||||
closeModalAndRefresh();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
setLoading(false);
|
||||
setModalErrorSnackMessage(err);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalWrapper
|
||||
modalOpen={open}
|
||||
onClose={() => {
|
||||
closeModalAndRefresh();
|
||||
}}
|
||||
title="Enable Bucket Quota"
|
||||
>
|
||||
<form
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
|
||||
enableBucketEncryption(e);
|
||||
}}
|
||||
>
|
||||
<Grid container>
|
||||
<Grid item xs={12} className={classes.formScrollable}>
|
||||
<Grid item xs={12}>
|
||||
<FormSwitchWrapper
|
||||
value="bucket_quota"
|
||||
id="bucket_quota"
|
||||
name="bucket_quota"
|
||||
checked={quotaEnabled}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setQuotaEnabled(event.target.checked);
|
||||
}}
|
||||
label={"Quota"}
|
||||
indicatorLabels={["On", "Off"]}
|
||||
/>
|
||||
</Grid>
|
||||
{quotaEnabled && (
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
<RadioGroupSelector
|
||||
currentSelection={quotaType}
|
||||
id="quota_type"
|
||||
name="quota_type"
|
||||
label="Quota Type"
|
||||
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
|
||||
setQuotaType(e.target.value as string);
|
||||
}}
|
||||
selectorOptions={[
|
||||
{ value: "hard", label: "Hard" },
|
||||
{ value: "fifo", label: "FIFO" },
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.multiContainer}>
|
||||
<div className={classes.quotaSizeContainer}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
id="quota_size"
|
||||
name="quota_size"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setQuotaSize(e.target.value);
|
||||
}}
|
||||
label="Quota"
|
||||
value={quotaSize}
|
||||
required
|
||||
min="1"
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.sizeFactorContainer}>
|
||||
<SelectWrapper
|
||||
label=" "
|
||||
id="quota_unit"
|
||||
name="quota_unit"
|
||||
value={quotaUnit}
|
||||
onChange={(
|
||||
e: React.ChangeEvent<{ value: unknown }>
|
||||
) => {
|
||||
setQuotaUnit(e.target.value as string);
|
||||
}}
|
||||
options={factorForDropdown()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<br />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.buttonContainer}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={loading}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
{loading && (
|
||||
<Grid item xs={12}>
|
||||
<LinearProgress />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</form>
|
||||
</ModalWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const connector = connect(null, {
|
||||
setModalErrorSnackMessage,
|
||||
});
|
||||
|
||||
export default withStyles(styles)(connector(EnableQuota));
|
||||
@@ -86,6 +86,11 @@ export interface BucketReplication {
|
||||
rules: BucketReplicationRule[];
|
||||
}
|
||||
|
||||
export interface BucketQuota {
|
||||
quota: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface QuotaRequest {
|
||||
enabled: boolean;
|
||||
quota_type: string;
|
||||
|
||||
@@ -206,9 +206,6 @@ const ListNotificationEndpoints = ({
|
||||
Add Notification Target
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<br />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TableWrapper
|
||||
itemActions={[]}
|
||||
|
||||
@@ -311,6 +311,10 @@ func (ac adminClient) setBucketQuota(ctx context.Context, bucket string, quota *
|
||||
return ac.client.SetBucketQuota(ctx, bucket, quota)
|
||||
}
|
||||
|
||||
func (ac adminClient) getBucketQuota(ctx context.Context, bucket string) (madmin.BucketQuota, error) {
|
||||
return ac.client.GetBucketQuota(ctx, bucket)
|
||||
}
|
||||
|
||||
// serverHealthInfo implements mc.ServerHealthInfo - Connect to a minio server and call Health Info Management API
|
||||
func (ac adminClient) serverHealthInfo(ctx context.Context, healthDataTypes []madmin.HealthDataType, deadline time.Duration) <-chan madmin.HealthInfo {
|
||||
return ac.client.ServerHealthInfo(ctx, healthDataTypes, deadline)
|
||||
|
||||
@@ -1586,7 +1586,7 @@ func init() {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/listObjectsResponse"
|
||||
"$ref": "#/definitions/bucketQuota"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
@@ -4264,6 +4264,21 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"bucketQuota": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"quota": {
|
||||
"type": "integer"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"hard",
|
||||
"fifo"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"bucketReplicationDestination": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -8714,7 +8729,7 @@ func init() {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/listObjectsResponse"
|
||||
"$ref": "#/definitions/bucketQuota"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
@@ -12032,6 +12047,21 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"bucketQuota": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"quota": {
|
||||
"type": "integer"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"hard",
|
||||
"fifo"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"bucketReplicationDestination": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -42,7 +42,7 @@ type GetBucketQuotaOK struct {
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.ListObjectsResponse `json:"body,omitempty"`
|
||||
Payload *models.BucketQuota `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetBucketQuotaOK creates GetBucketQuotaOK with default headers values
|
||||
@@ -52,13 +52,13 @@ func NewGetBucketQuotaOK() *GetBucketQuotaOK {
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get bucket quota o k response
|
||||
func (o *GetBucketQuotaOK) WithPayload(payload *models.ListObjectsResponse) *GetBucketQuotaOK {
|
||||
func (o *GetBucketQuotaOK) WithPayload(payload *models.BucketQuota) *GetBucketQuotaOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get bucket quota o k response
|
||||
func (o *GetBucketQuotaOK) SetPayload(payload *models.ListObjectsResponse) {
|
||||
func (o *GetBucketQuotaOK) SetPayload(payload *models.BucketQuota) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,15 @@ func registerBucketQuotaHandlers(api *operations.ConsoleAPI) {
|
||||
}
|
||||
return user_api.NewSetBucketQuotaOK()
|
||||
})
|
||||
|
||||
// get bucket quota
|
||||
api.UserAPIGetBucketQuotaHandler = user_api.GetBucketQuotaHandlerFunc(func(params user_api.GetBucketQuotaParams, session *models.Principal) middleware.Responder {
|
||||
resp, err := getBucketQuotaResponse(session, params)
|
||||
if err != nil {
|
||||
return user_api.NewGetBucketQuotaDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewGetBucketQuotaOK().WithPayload(resp)
|
||||
})
|
||||
}
|
||||
|
||||
func setBucketQuotaResponse(session *models.Principal, params user_api.SetBucketQuotaParams) *models.Error {
|
||||
@@ -85,3 +94,34 @@ func setBucketQuota(ctx context.Context, ac *adminClient, bucket *string, bucket
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getBucketQuotaResponse(session *models.Principal, params user_api.GetBucketQuotaParams) (*models.BucketQuota, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
quota, err := getBucketQuota(params.HTTPRequest.Context(), &adminClient, ¶ms.Name)
|
||||
if err != nil {
|
||||
return nil, &models.Error{
|
||||
Code: 500,
|
||||
Message: swag.String(err.Error()),
|
||||
}
|
||||
}
|
||||
return quota, nil
|
||||
}
|
||||
|
||||
func getBucketQuota(ctx context.Context, ac *adminClient, bucket *string) (*models.BucketQuota, error) {
|
||||
|
||||
quota, err := ac.getBucketQuota(ctx, *bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.BucketQuota{
|
||||
Quota: int64(quota.Quota),
|
||||
Type: string(quota.Type),
|
||||
}, nil
|
||||
}
|
||||
|
||||
12
swagger.yml
12
swagger.yml
@@ -597,7 +597,7 @@ paths:
|
||||
200:
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: "#/definitions/listObjectsResponse"
|
||||
$ref: "#/definitions/bucketQuota"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
@@ -3192,6 +3192,16 @@ definitions:
|
||||
properties:
|
||||
access:
|
||||
$ref: "#/definitions/bucketAccess"
|
||||
bucketQuota:
|
||||
type: object
|
||||
properties:
|
||||
quota:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- hard
|
||||
- fifo
|
||||
setBucketQuota:
|
||||
type: object
|
||||
required:
|
||||
|
||||
Reference in New Issue
Block a user