Added Server Info array to Basic dashboard (#963)

* Added Servers array to admin_info api

* Added TableWrapper, wrap

* Created Server table

* Added Servers array to admin_info api

Added TableWrapper, wrap

Created Server table

* Removed testing element

* Formatted server uptime with niceDays

* Added Servers array to admin_info api

Added TableWrapper, wrap

Created Server table

* Removed testing element

* Formatted server uptime with niceDays

* Formatted uptime using niceDays

* Sorted server table by endpoint

Co-authored-by: Harshavardhana <harsha@minio.io>
This commit is contained in:
jinapurapu
2021-08-24 11:13:26 -07:00
committed by GitHub
parent 4c01be21ca
commit 4306d0f661
7 changed files with 309 additions and 12 deletions

View File

@@ -42,6 +42,9 @@ type AdminInfoResponse struct {
// objects
Objects int64 `json:"objects,omitempty"`
// servers
Servers []*ServerProperties `json:"servers"`
// usage
Usage int64 `json:"usage,omitempty"`
@@ -53,6 +56,10 @@ type AdminInfoResponse struct {
func (m *AdminInfoResponse) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateServers(formats); err != nil {
res = append(res, err)
}
if err := m.validateWidgets(formats); err != nil {
res = append(res, err)
}
@@ -63,6 +70,30 @@ func (m *AdminInfoResponse) Validate(formats strfmt.Registry) error {
return nil
}
func (m *AdminInfoResponse) validateServers(formats strfmt.Registry) error {
if swag.IsZero(m.Servers) { // not required
return nil
}
for i := 0; i < len(m.Servers); i++ {
if swag.IsZero(m.Servers[i]) { // not required
continue
}
if m.Servers[i] != nil {
if err := m.Servers[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("servers" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *AdminInfoResponse) validateWidgets(formats strfmt.Registry) error {
if swag.IsZero(m.Widgets) { // not required
return nil
@@ -91,6 +122,10 @@ func (m *AdminInfoResponse) validateWidgets(formats strfmt.Registry) error {
func (m *AdminInfoResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateServers(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateWidgets(ctx, formats); err != nil {
res = append(res, err)
}
@@ -101,6 +136,24 @@ func (m *AdminInfoResponse) ContextValidate(ctx context.Context, formats strfmt.
return nil
}
func (m *AdminInfoResponse) contextValidateServers(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Servers); i++ {
if m.Servers[i] != nil {
if err := m.Servers[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("servers" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *AdminInfoResponse) contextValidateWidgets(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Widgets); i++ {

View File

@@ -0,0 +1,82 @@
// 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 (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// ServerProperties server properties
//
// swagger:model serverProperties
type ServerProperties struct {
// commit ID
CommitID string `json:"commitID,omitempty"`
// endpoint
Endpoint string `json:"endpoint,omitempty"`
// pool number
PoolNumber int64 `json:"poolNumber,omitempty"`
// state
State string `json:"state,omitempty"`
// uptime
Uptime string `json:"uptime,omitempty"`
// version
Version string `json:"version,omitempty"`
}
// Validate validates this server properties
func (m *ServerProperties) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this server properties based on context it is used
func (m *ServerProperties) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *ServerProperties) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ServerProperties) UnmarshalBinary(b []byte) error {
var res ServerProperties
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -14,17 +14,20 @@
// 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, { Fragment } from "react";
import React, { Fragment, useState } from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import clsx from "clsx";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import { Usage } from "../types";
import { niceBytes } from "../../../../common/utils";
import { Usage, ServerInfo } from "../types";
import { niceBytes, niceDays } from "../../../../common/utils";
import AllBucketsIcon from "../../../../icons/AllBucketsIcon";
import UsageIcon from "../../../../icons/UsageIcon";
import DnsIcon from "@material-ui/icons/Dns";
import EgressIcon from "../../../../icons/EgressIcon";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import { TableContainer } from "@material-ui/core";
const styles = (theme: Theme) =>
createStyles({
@@ -57,6 +60,7 @@ const styles = (theme: Theme) =>
},
notationContainer: {
display: "flex",
flexWrap: "wrap",
},
dashboardBG: {
width: 390,
@@ -120,6 +124,45 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
return usage.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
const serverColumns = [
{
label: "Endpoint",
elementKey: "endpoint",
},
{
label: "Status",
elementKey: "state",
},
{
label: "Uptime",
elementKey: "uptime",
},
{
label: "Version",
elementKey: "version",
},
];
const makeServerArray = (usage: Usage | null) => {
if (usage != null) {
usage.servers.forEach(s => s.uptime = niceDays(s.uptime))
return usage.servers.sort(function (a, b) {
var nameA = a.endpoint.toUpperCase();
var nameB = b.endpoint.toUpperCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
}
else return [];
};
const serverArray = makeServerArray(usage);
return (
<Fragment>
<div className={classes.dashboardBG} />
@@ -172,6 +215,24 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
{usage ? prettyNumber(usage.objects) : 0}
</Typography>
</Paper>
<Grid container direction="row" alignItems="center">
<Grid item className={classes.icon}>
<DnsIcon />
</Grid>
<Grid item>
<Typography className={classes.elementTitle}>
{" "}
Servers
</Typography>
</Grid>
<TableWrapper
columns={serverColumns}
isLoading={false}
records={serverArray}
entityName="Servers"
idField="endpoint"
/>
</Grid>
</Grid>
</Grid>
</Grid>

View File

@@ -19,4 +19,14 @@ export interface Usage {
buckets: number;
objects: number;
widgets?: any;
servers: ServerInfo[];
}
export interface ServerInfo {
state: string;
endpoint: string;
uptime: string;
version: string;
commitID: string;
poolNumber: number;
}

View File

@@ -24,6 +24,7 @@ import (
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
@@ -62,6 +63,7 @@ type UsageInfo struct {
Objects int64
Usage int64
DisksUsage int64
Servers []*models.ServerProperties
}
// GetAdminInfo invokes admin info and returns a parsed `UsageInfo` structure
@@ -80,11 +82,27 @@ func GetAdminInfo(ctx context.Context, client MinioAdmin) (*UsageInfo, error) {
}
}
//serverArray contains the serverProperties which describe the servers in the network
var serverArray []*models.ServerProperties
for _, serv := range serverInfo.Servers {
var newServer = &models.ServerProperties{
State: serv.State,
Endpoint: serv.Endpoint,
Uptime: strconv.Itoa(int(serv.Uptime)),
Version: serv.Version,
CommitID: serv.CommitID,
PoolNumber: int64(serv.PoolNumber),
}
serverArray = append(serverArray, newServer)
}
return &UsageInfo{
Buckets: int64(serverInfo.Buckets.Count),
Objects: int64(serverInfo.Objects.Count),
Usage: int64(serverInfo.Usage.Size),
DisksUsage: usedSpace,
Servers: serverArray,
}, nil
}
@@ -820,6 +838,7 @@ func getUsageWidgetsForDeployment(prometheusURL string, mAdmin *madmin.AdminClie
Buckets: usage.Buckets,
Objects: usage.Objects,
Usage: usage.Usage,
Servers: usage.Servers,
}
return sessionResp, nil
}

View File

@@ -3517,6 +3517,12 @@ func init() {
"objects": {
"type": "integer"
},
"servers": {
"type": "array",
"items": {
"$ref": "#/definitions/serverProperties"
}
},
"usage": {
"type": "integer"
},
@@ -4855,6 +4861,29 @@ func init() {
}
}
},
"serverProperties": {
"type": "object",
"properties": {
"commitID": {
"type": "string"
},
"endpoint": {
"type": "string"
},
"poolNumber": {
"type": "integer"
},
"state": {
"type": "string"
},
"uptime": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"serviceAccountCreds": {
"type": "object",
"properties": {
@@ -8935,6 +8964,12 @@ func init() {
"objects": {
"type": "integer"
},
"servers": {
"type": "array",
"items": {
"$ref": "#/definitions/serverProperties"
}
},
"usage": {
"type": "integer"
},
@@ -10273,6 +10308,29 @@ func init() {
}
}
},
"serverProperties": {
"type": "object",
"properties": {
"commitID": {
"type": "string"
},
"endpoint": {
"type": "string"
},
"poolNumber": {
"type": "integer"
},
"state": {
"type": "string"
},
"uptime": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"serviceAccountCreds": {
"type": "object",
"properties": {

View File

@@ -389,7 +389,7 @@ paths:
schema:
type: array
items:
$ref: "#/definitions/deleteFile"
$ref: "#/definitions/deleteFile"
responses:
200:
description: A successful response.
@@ -1046,7 +1046,7 @@ paths:
$ref: "#/definitions/error"
tags:
- UserAPI
/buckets/{bucket_name}/rewind/{date}:
get:
summary: Get objects in a bucket for a rewind date
@@ -1074,7 +1074,7 @@ paths:
schema:
$ref: "#/definitions/error"
tags:
- UserAPI
- UserAPI
/service-accounts:
get:
@@ -1935,7 +1935,6 @@ paths:
tags:
- AdminAPI
/admin/info:
get:
summary: Returns information about the deployment
@@ -3085,6 +3084,25 @@ definitions:
type: array
items:
$ref: "#/definitions/widget"
servers:
type: array
items:
$ref: "#/definitions/serverProperties"
serverProperties:
type: object
properties:
state:
type: string
endpoint:
type: string
uptime:
type: string
version:
type: string
commitID:
type: string
poolNumber:
type: integer
arnsResponse:
type: object
properties:
@@ -3300,7 +3318,6 @@ definitions:
object_locking_enabled:
type: boolean
logSearchResponse:
type: object
properties:
@@ -3308,8 +3325,6 @@ definitions:
type: object
title: list of log search responses
objectLegalHoldStatus:
type: string
enum:
@@ -3559,7 +3574,6 @@ definitions:
items:
$ref: "#/definitions/permissionAction"
tier_s3:
type: object
properties:
@@ -3679,7 +3693,7 @@ definitions:
type: string
name:
type: string
rewindResponse:
type: object
properties: