diff --git a/models/tier_azure.go b/models/tier_azure.go index eeec2e90ba..ef0a436205 100644 --- a/models/tier_azure.go +++ b/models/tier_azure.go @@ -49,11 +49,20 @@ type TierAzure struct { // name Name string `json:"name,omitempty"` + // objects + Objects string `json:"objects,omitempty"` + // prefix Prefix string `json:"prefix,omitempty"` // region Region string `json:"region,omitempty"` + + // usage + Usage string `json:"usage,omitempty"` + + // versions + Versions string `json:"versions,omitempty"` } // Validate validates this tier azure diff --git a/models/tier_gcs.go b/models/tier_gcs.go index e497e89016..5ae3221075 100644 --- a/models/tier_gcs.go +++ b/models/tier_gcs.go @@ -46,11 +46,20 @@ type TierGcs struct { // name Name string `json:"name,omitempty"` + // objects + Objects string `json:"objects,omitempty"` + // prefix Prefix string `json:"prefix,omitempty"` // region Region string `json:"region,omitempty"` + + // usage + Usage string `json:"usage,omitempty"` + + // versions + Versions string `json:"versions,omitempty"` } // Validate validates this tier gcs diff --git a/models/tier_s3.go b/models/tier_s3.go index 6ae330a585..213a688b74 100644 --- a/models/tier_s3.go +++ b/models/tier_s3.go @@ -46,6 +46,9 @@ type TierS3 struct { // name Name string `json:"name,omitempty"` + // objects + Objects string `json:"objects,omitempty"` + // prefix Prefix string `json:"prefix,omitempty"` @@ -57,6 +60,12 @@ type TierS3 struct { // storageclass Storageclass string `json:"storageclass,omitempty"` + + // usage + Usage string `json:"usage,omitempty"` + + // versions + Versions string `json:"versions,omitempty"` } // Validate validates this tier s3 diff --git a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx index de7886872c..9cfbf19735 100644 --- a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx +++ b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx @@ -218,6 +218,36 @@ const ListTiersConfiguration = ({ return ""; }; + const renderTierUsage = (item: ITierElement) => { + const endpoint = get(item, `${item.type}.usage`, ""); + + if (endpoint !== null) { + return endpoint; + } + + return ""; + }; + + const renderTierObjects = (item: ITierElement) => { + const endpoint = get(item, `${item.type}.objects`, ""); + + if (endpoint !== null) { + return endpoint; + } + + return ""; + }; + + const renderTierVersions = (item: ITierElement) => { + const endpoint = get(item, `${item.type}.versions`, ""); + + if (endpoint !== null) { + return endpoint; + } + + return ""; + }; + const closeTierCredentials = () => { setUpdateCredentialsOpen(false); }; @@ -330,6 +360,24 @@ const ListTiersConfiguration = ({ renderFunction: renderTierRegion, renderFullObject: true, }, + { + label: "Usage", + elementKey: "type", + renderFunction: renderTierUsage, + renderFullObject: true, + }, + { + label: "Objects", + elementKey: "type", + renderFunction: renderTierObjects, + renderFullObject: true, + }, + { + label: "Versions", + elementKey: "type", + renderFunction: renderTierVersions, + renderFullObject: true, + }, ]} isLoading={isLoading} records={filteredRecords} diff --git a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/types.ts b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/types.ts index ccd26b308b..b88d5a8fc8 100644 --- a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/types.ts +++ b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/types.ts @@ -23,6 +23,9 @@ export interface ITierS3 { prefix: string; region: string; storageclass: string; + usage: string; + objects: string; + versions: string; } export interface ITierGCS { @@ -33,6 +36,9 @@ export interface ITierGCS { prefix: string; region: string; storageclass: string; + usage: string; + objects: string; + versions: string; } export interface ITierAzure { @@ -44,6 +50,9 @@ export interface ITierAzure { prefix: string; region: string; storageclass: string; + usage: string; + objects: string; + versions: string; } export interface ITierElement { diff --git a/restapi/admin_tiers.go b/restapi/admin_tiers.go index 3b3ea2ca70..37ccc8c117 100644 --- a/restapi/admin_tiers.go +++ b/restapi/admin_tiers.go @@ -19,8 +19,10 @@ package restapi import ( "context" "encoding/base64" + "strconv" "time" + "github.com/dustin/go-humanize" "github.com/minio/madmin-go" "github.com/go-openapi/runtime/middleware" @@ -71,10 +73,12 @@ func getTiers(ctx context.Context, client MinioAdmin) (*models.TierListResponse, if err != nil { return nil, err } - + tierInfo, err := client.tierStats(ctx) + if err != nil { + return nil, err + } var tiersList []*models.Tier for i := range tiers { - switch tiers[i].Type { case madmin.S3: tiersList = append(tiersList, &models.Tier{ @@ -88,6 +92,9 @@ func getTiers(ctx context.Context, client MinioAdmin) (*models.TierListResponse, Region: tiers[i].S3.Region, Secretkey: tiers[i].S3.SecretKey, Storageclass: tiers[i].S3.StorageClass, + Usage: humanize.IBytes(tierInfo[i+1].Stats.TotalSize), + Objects: strconv.Itoa(tierInfo[i+1].Stats.NumObjects), + Versions: strconv.Itoa(tierInfo[i+1].Stats.NumVersions), }, }) case madmin.GCS: @@ -100,6 +107,9 @@ func getTiers(ctx context.Context, client MinioAdmin) (*models.TierListResponse, Name: tiers[i].Name, Prefix: tiers[i].GCS.Prefix, Region: tiers[i].GCS.Region, + Usage: humanize.IBytes(tierInfo[i+1].Stats.TotalSize), + Objects: strconv.Itoa(tierInfo[i+1].Stats.NumObjects), + Versions: strconv.Itoa(tierInfo[i+1].Stats.NumVersions), }, }) case madmin.Azure: @@ -113,6 +123,9 @@ func getTiers(ctx context.Context, client MinioAdmin) (*models.TierListResponse, Name: tiers[i].Name, Prefix: tiers[i].Azure.Prefix, Region: tiers[i].Azure.Region, + Usage: humanize.IBytes(tierInfo[i+1].Stats.TotalSize), + Objects: strconv.Itoa(tierInfo[i+1].Stats.NumObjects), + Versions: strconv.Itoa(tierInfo[i+1].Stats.NumVersions), }, }) case madmin.Unsupported: diff --git a/restapi/admin_tiers_test.go b/restapi/admin_tiers_test.go index fd24191a41..a712f391c5 100644 --- a/restapi/admin_tiers_test.go +++ b/restapi/admin_tiers_test.go @@ -36,6 +36,14 @@ func (ac adminClientMock) listTiers(ctx context.Context) ([]*madmin.TierConfig, return minioListTiersMock(ctx) } +// assigning mock at runtime instead of compile time +var minioTierStatsMock func(ctx context.Context) ([]madmin.TierInfo, error) + +// mock function of tierStats() +func (ac adminClientMock) tierStats(ctx context.Context) ([]madmin.TierInfo, error) { + return minioTierStatsMock(ctx) +} + // assigning mock at runtime instead of compile time var minioAddTiersMock func(ctx context.Context, tier *madmin.TierConfig) error @@ -79,6 +87,19 @@ func TestGetTiers(t *testing.T) { }, } + returnStatsMock := []madmin.TierInfo{ + { + Name: "STANDARD", + Type: "internal", + Stats: madmin.TierStats{NumObjects: 2, NumVersions: 2, TotalSize: 228915}, + }, + { + Name: "S3 Tier", + Type: "s3", + Stats: madmin.TierStats{NumObjects: 0, NumVersions: 0, TotalSize: 0}, + }, + } + expectedOutput := &models.TierListResponse{ Items: []*models.Tier{ { @@ -92,6 +113,9 @@ func TestGetTiers(t *testing.T) { Prefix: "pref1", Region: "us-west-1", Storageclass: "TT1", + Usage: "0 B", + Objects: "0", + Versions: "0", }, }, }, @@ -101,6 +125,10 @@ func TestGetTiers(t *testing.T) { return returnListMock, nil } + minioTierStatsMock = func(ctx context.Context) ([]madmin.TierInfo, error) { + return returnStatsMock, nil + } + tiersList, err := getTiers(ctx, adminClient) if err != nil { diff --git a/restapi/client-admin.go b/restapi/client-admin.go index d1403a020c..f5eed17b4d 100644 --- a/restapi/client-admin.go +++ b/restapi/client-admin.go @@ -106,6 +106,8 @@ type MinioAdmin interface { serverHealthInfo(ctx context.Context, healthDataTypes []madmin.HealthDataType, deadline time.Duration) (interface{}, string, error) // List Tiers listTiers(ctx context.Context) ([]*madmin.TierConfig, error) + // Tier Info + tierStats(ctx context.Context) ([]madmin.TierInfo, error) // Add Tier addTier(ctx context.Context, tier *madmin.TierConfig) error // Edit Tier Credentials @@ -412,6 +414,11 @@ func (ac AdminClient) listTiers(ctx context.Context) ([]*madmin.TierConfig, erro return ac.Client.ListTiers(ctx) } +// implements madmin.tierStats() +func (ac AdminClient) tierStats(ctx context.Context) ([]madmin.TierInfo, error) { + return ac.Client.TierStats(ctx) +} + // implements madmin.AddTier() func (ac AdminClient) addTier(ctx context.Context, cfg *madmin.TierConfig) error { return ac.Client.AddTier(ctx, cfg) diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 911c4391e9..70271b598e 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -6502,11 +6502,20 @@ func init() { "name": { "type": "string" }, + "objects": { + "type": "string" + }, "prefix": { "type": "string" }, "region": { "type": "string" + }, + "usage": { + "type": "string" + }, + "versions": { + "type": "string" } } }, @@ -6525,11 +6534,20 @@ func init() { "name": { "type": "string" }, + "objects": { + "type": "string" + }, "prefix": { "type": "string" }, "region": { "type": "string" + }, + "usage": { + "type": "string" + }, + "versions": { + "type": "string" } } }, @@ -6548,6 +6566,9 @@ func init() { "name": { "type": "string" }, + "objects": { + "type": "string" + }, "prefix": { "type": "string" }, @@ -6559,6 +6580,12 @@ func init() { }, "storageclass": { "type": "string" + }, + "usage": { + "type": "string" + }, + "versions": { + "type": "string" } } }, @@ -13422,11 +13449,20 @@ func init() { "name": { "type": "string" }, + "objects": { + "type": "string" + }, "prefix": { "type": "string" }, "region": { "type": "string" + }, + "usage": { + "type": "string" + }, + "versions": { + "type": "string" } } }, @@ -13445,11 +13481,20 @@ func init() { "name": { "type": "string" }, + "objects": { + "type": "string" + }, "prefix": { "type": "string" }, "region": { "type": "string" + }, + "usage": { + "type": "string" + }, + "versions": { + "type": "string" } } }, @@ -13468,6 +13513,9 @@ func init() { "name": { "type": "string" }, + "objects": { + "type": "string" + }, "prefix": { "type": "string" }, @@ -13479,6 +13527,12 @@ func init() { }, "storageclass": { "type": "string" + }, + "usage": { + "type": "string" + }, + "versions": { + "type": "string" } } }, diff --git a/swagger-console.yml b/swagger-console.yml index 555e9127af..e9f6f11782 100644 --- a/swagger-console.yml +++ b/swagger-console.yml @@ -4454,6 +4454,12 @@ definitions: type: string storageclass: type: string + usage: + type: string + objects: + type: string + versions: + type: string tier_azure: type: object @@ -4472,6 +4478,12 @@ definitions: type: string region: type: string + usage: + type: string + objects: + type: string + versions: + type: string tier_gcs: type: object @@ -4488,6 +4500,12 @@ definitions: type: string region: type: string + usage: + type: string + objects: + type: string + versions: + type: string deleteFile: type: object