mirror of
https://github.com/pgsty/minio.git
synced 2026-11-01 05:12:07 +03:00
fix: return current bucket inventory from account info
Signed-off-by: Feng Ruohang <rh@vonng.com>
(cherry picked from commit 6921f8c186)
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright (c) 2026 PGSTY
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/minio/madmin-go/v3"
|
||||||
|
"github.com/minio/minio/internal/cachevalue"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccountInfoReflectsBucketMutations(t *testing.T) {
|
||||||
|
ctx := t.Context()
|
||||||
|
bed, err := prepareAdminErasureTestBed(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer bed.TearDown()
|
||||||
|
previousCache := listBucketsCache
|
||||||
|
defer func() { listBucketsCache = previousCache }()
|
||||||
|
|
||||||
|
// Hold a real pre-mutation snapshot past the assertions so the regression
|
||||||
|
// cannot disappear merely because a slow test outlasted the cache TTL.
|
||||||
|
freezeListing := func() {
|
||||||
|
t.Helper()
|
||||||
|
buckets, err := bed.objLayer.ListBuckets(ctx, BucketOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
listBucketsCache = cachevalue.NewFromFunc(time.Hour, cachevalue.Opts{}, func(context.Context) ([]BucketInfo, error) {
|
||||||
|
return buckets, nil
|
||||||
|
})
|
||||||
|
if _, err := listBucketsCache.GetWithCtx(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const bucket = "account-info-freshness"
|
||||||
|
assertPresent := func(want bool) {
|
||||||
|
t.Helper()
|
||||||
|
req, err := buildAdminRequest(nil, http.MethodGet, "/accountinfo", 0, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
bed.router.ServeHTTP(rec, req)
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("account info: %d %s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
var info madmin.AccountInfo
|
||||||
|
if err := json.Unmarshal(rec.Body.Bytes(), &info); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
found := false
|
||||||
|
for _, item := range info.Buckets {
|
||||||
|
if item.Name == bucket {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found != want {
|
||||||
|
t.Errorf("account info bucket present = %v, want %v", found, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freezeListing()
|
||||||
|
if err := bed.objLayer.MakeBucket(ctx, bucket, MakeBucketOptions{}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assertPresent(true)
|
||||||
|
freezeListing()
|
||||||
|
if err := bed.objLayer.DeleteBucket(ctx, bucket, DeleteBucketOptions{}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assertPresent(false)
|
||||||
|
}
|
||||||
@@ -1447,7 +1447,10 @@ func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
return buckets[i].Name < buckets[j].Name
|
return buckets[i].Name < buckets[j].Name
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
buckets, err = objectAPI.ListBuckets(ctx, BucketOptions{Cached: true})
|
// Console refreshes this inventory immediately after bucket mutations.
|
||||||
|
// A stale cached list can otherwise hide a creation or retain a deletion
|
||||||
|
// indefinitely in the client's snapshot.
|
||||||
|
buckets, err = objectAPI.ListBuckets(ctx, BucketOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user