mirror of
https://github.com/minio/minio.git
synced 2025-02-02 17:35:58 -05:00
Integrate existing remove bucket functionality from newux to current UI (#5289)
This commit takes the existing remove bucket functionality written by brendanashworth, integrates it to the current UI with a dropdown for each bucket, and fixes small issues that were present, like the dropdown not disappearing after the user clicks on 'Delete' for certain buckets. This feature only deletes a bucket that is empty (that has no objects). Fixes #4166
This commit is contained in:
parent
baaf67d82e
commit
659f724f4c
@ -41,6 +41,8 @@ import _Login from './js/components/Login.js'
|
|||||||
import _Browse from './js/components/Browse.js'
|
import _Browse from './js/components/Browse.js'
|
||||||
import fontAwesome from 'font-awesome/css/font-awesome.css'
|
import fontAwesome from 'font-awesome/css/font-awesome.css'
|
||||||
|
|
||||||
|
import MaterialDesignIconicFonts from 'material-design-iconic-font/dist/css/material-design-iconic-font.min.css'
|
||||||
|
|
||||||
import Web from './js/web'
|
import Web from './js/web'
|
||||||
window.Web = Web
|
window.Web = Web
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ export const SET_CURRENT_BUCKET = 'SET_CURRENT_BUCKET'
|
|||||||
export const SET_CURRENT_PATH = 'SET_CURRENT_PATH'
|
export const SET_CURRENT_PATH = 'SET_CURRENT_PATH'
|
||||||
export const SET_BUCKETS = 'SET_BUCKETS'
|
export const SET_BUCKETS = 'SET_BUCKETS'
|
||||||
export const ADD_BUCKET = 'ADD_BUCKET'
|
export const ADD_BUCKET = 'ADD_BUCKET'
|
||||||
|
export const REMOVE_BUCKET = 'REMOVE_BUCKET'
|
||||||
|
export const SHOW_BUCKET_DROPDOWN = 'SHOW_BUCKET_DROPDOWN'
|
||||||
export const SET_VISIBLE_BUCKETS = 'SET_VISIBLE_BUCKETS'
|
export const SET_VISIBLE_BUCKETS = 'SET_VISIBLE_BUCKETS'
|
||||||
export const SET_OBJECTS = 'SET_OBJECTS'
|
export const SET_OBJECTS = 'SET_OBJECTS'
|
||||||
export const APPEND_OBJECTS = 'APPEND_OBJECTS'
|
export const APPEND_OBJECTS = 'APPEND_OBJECTS'
|
||||||
@ -173,6 +175,27 @@ export const addBucket = bucket => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const removeBucket = bucket => {
|
||||||
|
return {
|
||||||
|
type: REMOVE_BUCKET,
|
||||||
|
bucket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showBucketDropdown = bucket => {
|
||||||
|
return {
|
||||||
|
type: SHOW_BUCKET_DROPDOWN,
|
||||||
|
showBucketDropdown: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hideBucketDropdown = bucket => {
|
||||||
|
return {
|
||||||
|
type: SHOW_BUCKET_DROPDOWN,
|
||||||
|
showBucketDropdown: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const showMakeBucketModal = () => {
|
export const showMakeBucketModal = () => {
|
||||||
return {
|
return {
|
||||||
type: SHOW_MAKEBUCKET_MODAL,
|
type: SHOW_MAKEBUCKET_MODAL,
|
||||||
@ -314,6 +337,31 @@ export const selectBucket = (newCurrentBucket, prefix) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteBucket = (bucket) => {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
// DeleteBucket() RPC call will ONLY delete a bucket if it is empty of
|
||||||
|
// objects. This means a call can just be sent, as it is entirely reversable
|
||||||
|
// and won't do any permanent damage.
|
||||||
|
web.DeleteBucket({
|
||||||
|
bucketName: bucket
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
dispatch(showAlert({
|
||||||
|
type: 'info',
|
||||||
|
message: `Bucket '${bucket}' has been deleted.`
|
||||||
|
}))
|
||||||
|
dispatch(removeBucket(bucket))
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
let message = err.message
|
||||||
|
dispatch(showAlert({
|
||||||
|
type: 'danger',
|
||||||
|
message: message
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const listObjects = () => {
|
export const listObjects = () => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const {buckets, currentBucket, currentPath, marker, objects, istruncated, web} = getState()
|
const {buckets, currentBucket, currentPath, marker, objects, istruncated, web} = getState()
|
||||||
|
@ -210,9 +210,19 @@ export default class Browse extends React.Component {
|
|||||||
dispatch(actions.hideAbout())
|
dispatch(actions.hideAbout())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleBucketDropdown(e) {
|
||||||
|
const {dispatch, showBucketDropdown} = this.props
|
||||||
|
if (showBucketDropdown) {
|
||||||
|
dispatch(actions.hideBucketDropdown())
|
||||||
|
} else {
|
||||||
|
dispatch(actions.showBucketDropdown())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
showBucketPolicy(e) {
|
showBucketPolicy(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const {dispatch} = this.props
|
const {dispatch} = this.props
|
||||||
|
this.toggleBucketDropdown(e)
|
||||||
dispatch(actions.showBucketPolicy())
|
dispatch(actions.showBucketPolicy())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,10 +232,17 @@ export default class Browse extends React.Component {
|
|||||||
dispatch(actions.hideBucketPolicy())
|
dispatch(actions.hideBucketPolicy())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteBucket(e, bucket) {
|
||||||
|
e.preventDefault()
|
||||||
|
const {dispatch} = this.props
|
||||||
|
this.toggleBucketDropdown(e)
|
||||||
|
dispatch(actions.deleteBucket(bucket))
|
||||||
|
browserHistory.push(`${minioBrowserPrefix}/`)
|
||||||
|
}
|
||||||
|
|
||||||
uploadFile(e) {
|
uploadFile(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const {dispatch, buckets} = this.props
|
const {dispatch, buckets, currentBucket} = this.props
|
||||||
|
|
||||||
if (buckets.length === 0) {
|
if (buckets.length === 0) {
|
||||||
dispatch(actions.showAlert({
|
dispatch(actions.showAlert({
|
||||||
type: 'danger',
|
type: 'danger',
|
||||||
@ -233,6 +250,13 @@ export default class Browse extends React.Component {
|
|||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (currentBucket === '') {
|
||||||
|
dispatch(actions.showAlert({
|
||||||
|
type: 'danger',
|
||||||
|
message: "Please choose a bucket before trying to upload files."
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
let file = e.target.files[0]
|
let file = e.target.files[0]
|
||||||
e.target.value = null
|
e.target.value = null
|
||||||
this.xhr = new XMLHttpRequest()
|
this.xhr = new XMLHttpRequest()
|
||||||
@ -577,7 +601,9 @@ export default class Browse extends React.Component {
|
|||||||
<SideBar searchBuckets={ this.searchBuckets.bind(this) }
|
<SideBar searchBuckets={ this.searchBuckets.bind(this) }
|
||||||
selectBucket={ this.selectBucket.bind(this) }
|
selectBucket={ this.selectBucket.bind(this) }
|
||||||
clickOutside={ this.hideSidebar.bind(this) }
|
clickOutside={ this.hideSidebar.bind(this) }
|
||||||
showPolicy={ this.showBucketPolicy.bind(this) } />
|
showPolicy={ this.showBucketPolicy.bind(this) }
|
||||||
|
deleteBucket={ this.deleteBucket.bind(this) }
|
||||||
|
toggleBucketDropdown={ this.toggleBucketDropdown.bind(this) } />
|
||||||
<div className="fe-body">
|
<div className="fe-body">
|
||||||
<div className={ 'list-actions' + (classNames({
|
<div className={ 'list-actions' + (classNames({
|
||||||
' list-actions-toggled': checkedObjects.length > 0
|
' list-actions-toggled': checkedObjects.length > 0
|
||||||
|
@ -21,8 +21,9 @@ import Scrollbars from 'react-custom-scrollbars/lib/Scrollbars'
|
|||||||
import connect from 'react-redux/lib/components/connect'
|
import connect from 'react-redux/lib/components/connect'
|
||||||
|
|
||||||
import logo from '../../img/logo.svg'
|
import logo from '../../img/logo.svg'
|
||||||
|
import Dropdown from 'react-bootstrap/lib/Dropdown'
|
||||||
|
|
||||||
let SideBar = ({visibleBuckets, loadBucket, currentBucket, selectBucket, searchBuckets, sidebarStatus, clickOutside, showPolicy}) => {
|
let SideBar = ({visibleBuckets, loadBucket, currentBucket, selectBucket, searchBuckets, sidebarStatus, clickOutside, showPolicy, deleteBucket, toggleBucketDropdown, showBucketDropdown}) => {
|
||||||
|
|
||||||
const list = visibleBuckets.map((bucket, i) => {
|
const list = visibleBuckets.map((bucket, i) => {
|
||||||
return <li className={ classNames({
|
return <li className={ classNames({
|
||||||
@ -33,7 +34,19 @@ let SideBar = ({visibleBuckets, loadBucket, currentBucket, selectBucket, searchB
|
|||||||
}) }>
|
}) }>
|
||||||
{ bucket }
|
{ bucket }
|
||||||
</a>
|
</a>
|
||||||
<i className="fesli-trigger" onClick={ showPolicy }></i>
|
<Dropdown open={bucket === currentBucket && showBucketDropdown} onToggle={toggleBucketDropdown} className="bucket-dropdown" id="bucket-dropdown">
|
||||||
|
<Dropdown.Toggle noCaret>
|
||||||
|
<i className="zmdi zmdi-more-vert" />
|
||||||
|
</Dropdown.Toggle>
|
||||||
|
<Dropdown.Menu className="dropdown-menu-right">
|
||||||
|
<li>
|
||||||
|
<a onClick={ showPolicy }>Edit policy</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a onClick={ (e) => deleteBucket(e, bucket) }>Delete</a>
|
||||||
|
</li>
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
</li>
|
</li>
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -80,6 +93,7 @@ export default connect(state => {
|
|||||||
visibleBuckets: state.visibleBuckets,
|
visibleBuckets: state.visibleBuckets,
|
||||||
loadBucket: state.loadBucket,
|
loadBucket: state.loadBucket,
|
||||||
currentBucket: state.currentBucket,
|
currentBucket: state.currentBucket,
|
||||||
|
showBucketDropdown: state.showBucketDropdown,
|
||||||
sidebarStatus: state.sidebarStatus
|
sidebarStatus: state.sidebarStatus
|
||||||
}
|
}
|
||||||
})(SideBar)
|
})(SideBar)
|
||||||
|
@ -25,6 +25,7 @@ export default (state = {
|
|||||||
storageInfo: {},
|
storageInfo: {},
|
||||||
serverInfo: {},
|
serverInfo: {},
|
||||||
currentBucket: '',
|
currentBucket: '',
|
||||||
|
showBucketDropdown: false,
|
||||||
currentPath: '',
|
currentPath: '',
|
||||||
showMakeBucketModal: false,
|
showMakeBucketModal: false,
|
||||||
uploads: {},
|
uploads: {},
|
||||||
@ -71,6 +72,14 @@ export default (state = {
|
|||||||
newState.buckets = [action.bucket, ...newState.buckets]
|
newState.buckets = [action.bucket, ...newState.buckets]
|
||||||
newState.visibleBuckets = [action.bucket, ...newState.visibleBuckets]
|
newState.visibleBuckets = [action.bucket, ...newState.visibleBuckets]
|
||||||
break
|
break
|
||||||
|
case actions.REMOVE_BUCKET:
|
||||||
|
newState.buckets = newState.buckets.filter(bucket => bucket != action.bucket)
|
||||||
|
newState.visibleBuckets = newState.visibleBuckets.filter(bucket => bucket != action.bucket)
|
||||||
|
newState.currentBucket = ""
|
||||||
|
break
|
||||||
|
case actions.SHOW_BUCKET_DROPDOWN:
|
||||||
|
newState.showBucketDropdown = action.showBucketDropdown
|
||||||
|
break
|
||||||
case actions.SET_VISIBLE_BUCKETS:
|
case actions.SET_VISIBLE_BUCKETS:
|
||||||
newState.visibleBuckets = action.visibleBuckets
|
newState.visibleBuckets = action.visibleBuckets
|
||||||
break
|
break
|
||||||
|
@ -87,6 +87,9 @@ export default class Web {
|
|||||||
MakeBucket(args) {
|
MakeBucket(args) {
|
||||||
return this.makeCall('MakeBucket', args)
|
return this.makeCall('MakeBucket', args)
|
||||||
}
|
}
|
||||||
|
DeleteBucket(args) {
|
||||||
|
return this.makeCall('DeleteBucket', args)
|
||||||
|
}
|
||||||
ListObjects(args) {
|
ListObjects(args) {
|
||||||
return this.makeCall('ListObjects', args)
|
return this.makeCall('ListObjects', args)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.fesli-trigger {
|
.bucket-dropdown .dropdown-toggle {
|
||||||
.opacity(0.6);
|
.opacity(0.6);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -132,17 +132,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fesli-trigger {
|
/* Dropdown */
|
||||||
.opacity(0);
|
.bucket-dropdown {
|
||||||
.transition(all);
|
|
||||||
.transition-duration(200ms);
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0px;
|
||||||
right: 0;
|
right: 0px;
|
||||||
width: 35px;
|
width: 35px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: url(../../img/more-h-light.svg) no-repeat top 20px left;
|
color: @white;
|
||||||
|
|
||||||
|
.dropdown-toggle {
|
||||||
|
.opacity(0);
|
||||||
|
.transition(all);
|
||||||
|
.transition-duration(200ms);
|
||||||
|
font-size: 20px;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu-right {
|
||||||
|
padding: 15px 0;
|
||||||
|
margin-top: -1px;
|
||||||
|
& li {
|
||||||
|
a:before {
|
||||||
|
content: none;
|
||||||
|
-webkit-box-shadow: @dropdown-shadow;
|
||||||
|
box-shadow: @dropdown-shadow;
|
||||||
|
}
|
||||||
|
&:not(.active):hover {
|
||||||
|
& > a {
|
||||||
|
color: @dropdown-link-hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar */
|
/* Scrollbar */
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
"humanize": "0.0.9",
|
"humanize": "0.0.9",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"local-storage-fallback": "^1.3.0",
|
"local-storage-fallback": "^1.3.0",
|
||||||
|
"material-design-iconic-font": "^2.2.0",
|
||||||
"mime-db": "^1.25.0",
|
"mime-db": "^1.25.0",
|
||||||
"mime-types": "^2.1.13",
|
"mime-types": "^2.1.13",
|
||||||
"moment": "^2.15.1",
|
"moment": "^2.15.1",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -145,6 +145,36 @@ func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, rep
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveBucketArgs - remove bucket args.
|
||||||
|
type RemoveBucketArgs struct {
|
||||||
|
BucketName string `json:"bucketName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBucket - removes a bucket, must be empty.
|
||||||
|
func (web *webAPIHandlers) DeleteBucket(r *http.Request, args *RemoveBucketArgs, reply *WebGenericRep) error {
|
||||||
|
objectAPI := web.ObjectAPI()
|
||||||
|
if objectAPI == nil {
|
||||||
|
return toJSONError(errServerNotInitialized)
|
||||||
|
}
|
||||||
|
if !isHTTPRequestValid(r) {
|
||||||
|
return toJSONError(errAuthentication)
|
||||||
|
}
|
||||||
|
|
||||||
|
bucketLock := globalNSMutex.NewNSLock(args.BucketName, "")
|
||||||
|
if err := bucketLock.GetLock(globalObjectTimeout); err != nil {
|
||||||
|
return toJSONError(errOperationTimedOut)
|
||||||
|
}
|
||||||
|
defer bucketLock.Unlock()
|
||||||
|
|
||||||
|
err := objectAPI.DeleteBucket(args.BucketName)
|
||||||
|
if err != nil {
|
||||||
|
return toJSONError(err, args.BucketName)
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.UIVersion = browser.UIVersion
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListBucketsRep - list buckets response
|
// ListBucketsRep - list buckets response
|
||||||
type ListBucketsRep struct {
|
type ListBucketsRep struct {
|
||||||
Buckets []WebBucketInfo `json:"buckets"`
|
Buckets []WebBucketInfo `json:"buckets"`
|
||||||
|
@ -305,6 +305,107 @@ func testMakeBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper for calling DeleteBucket handler
|
||||||
|
func TestWebHandlerDeleteBucket(t *testing.T) {
|
||||||
|
ExecObjectLayerTest(t, testDeleteBucketWebHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testDeleteBucketWebHandler - Test DeleteBucket web handler
|
||||||
|
func testDeleteBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||||
|
apiRouter := initTestWebRPCEndPoint(obj)
|
||||||
|
|
||||||
|
credentials := globalServerConfig.GetCredential()
|
||||||
|
token, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not get RPC token, %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
bucketName := getRandomBucketName()
|
||||||
|
err = obj.MakeBucketWithLocation(bucketName, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create bucket: %s (%s)", err.Error(), instanceType)
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
bucketName string
|
||||||
|
// Whether or not to put an object into the bucket.
|
||||||
|
initWithObject bool
|
||||||
|
token string
|
||||||
|
// Expected error (error must only contain this string to pass test)
|
||||||
|
// Empty string = no error
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{"", false, token, "Bucket Name is invalid"},
|
||||||
|
{".", false, "auth", "Authentication failed"},
|
||||||
|
{".", false, token, "Bucket Name . is invalid"},
|
||||||
|
{"ab", false, token, "Bucket Name ab is invalid"},
|
||||||
|
{"minio", false, "false token", "Authentication failed"},
|
||||||
|
{"minio", false, token, "specified bucket minio does not exist"},
|
||||||
|
{bucketName, false, token, ""},
|
||||||
|
{bucketName, true, token, "Bucket not empty"},
|
||||||
|
{bucketName, false, "", "Authentication failed"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if test.initWithObject {
|
||||||
|
data := bytes.NewBufferString("hello")
|
||||||
|
_, err = obj.PutObject(test.bucketName, "object", mustGetHashReader(t, data, int64(data.Len()), "", ""), nil)
|
||||||
|
// _, err = obj.PutObject(test.bucketName, "object", int64(data.Len()), data, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not put object to %s, %s", test.bucketName, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
makeBucketRequest := MakeBucketArgs{BucketName: test.bucketName}
|
||||||
|
makeBucketReply := &WebGenericRep{}
|
||||||
|
|
||||||
|
req, err := newTestWebRPCRequest("Web.DeleteBucket", test.token, makeBucketRequest)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to create HTTP request: <ERROR> %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
apiRouter.ServeHTTP(rec, req)
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Errorf("expected the response status to be `%d`, but instead found `%d`", http.StatusOK, rec.Code)
|
||||||
|
}
|
||||||
|
err = getTestWebRPCResponse(rec, &makeBucketReply)
|
||||||
|
|
||||||
|
if test.expect != "" {
|
||||||
|
if err == nil {
|
||||||
|
// If we expected an error, but didn't get one.
|
||||||
|
t.Errorf("expected `..%s..` but got nil error", test.expect)
|
||||||
|
} else if !strings.Contains(err.Error(), test.expect) {
|
||||||
|
// If we got an error that wasn't what we expected.
|
||||||
|
t.Errorf("expected `..%s..` but got `%s`", test.expect, err.Error())
|
||||||
|
}
|
||||||
|
} else if test.expect == "" && err != nil {
|
||||||
|
t.Errorf("expected test success, but got `%s`", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we created the bucket with an object, now delete the object to cleanup.
|
||||||
|
if test.initWithObject {
|
||||||
|
err = obj.DeleteObject(test.bucketName, "object")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not delete object, %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it did not succeed in deleting the bucket, don't try and recreate it.
|
||||||
|
// Or, it'll fail if there was an object.
|
||||||
|
if err != nil || test.initWithObject {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = obj.MakeBucketWithLocation(bucketName, "")
|
||||||
|
if err != nil {
|
||||||
|
// failed to create new bucket, abort.
|
||||||
|
t.Fatalf("failed to create new bucket (%s): %s", instanceType, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wrapper for calling ListBuckets Web Handler
|
// Wrapper for calling ListBuckets Web Handler
|
||||||
func TestWebHandlerListBuckets(t *testing.T) {
|
func TestWebHandlerListBuckets(t *testing.T) {
|
||||||
ExecObjectLayerTest(t, testListBucketsWebHandler)
|
ExecObjectLayerTest(t, testListBucketsWebHandler)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user