diff --git a/cmd/admin-subnet-health.go b/cmd/admin-subnet-health.go index 2d4b6a4e5f..9145dc2246 100644 --- a/cmd/admin-subnet-health.go +++ b/cmd/admin-subnet-health.go @@ -19,6 +19,7 @@ package cmd import ( "context" gojson "encoding/json" + "errors" "flag" "fmt" "os" @@ -30,23 +31,21 @@ import ( "github.com/fatih/color" "github.com/klauspost/compress/gzip" "github.com/minio/cli" - json "github.com/minio/mc/pkg/colorjson" - "github.com/minio/mc/pkg/probe" "github.com/minio/minio/pkg/console" "github.com/minio/minio/pkg/madmin" ) -var adminOBDFlags = []cli.Flag{ - OBDDataTypeFlag{ +var adminHealthFlags = []cli.Flag{ + HealthDataTypeFlag{ Name: "test", - Usage: "choose OBD tests to run [" + options.String() + "]", + Usage: "choose health tests to run [" + options.String() + "]", Value: nil, EnvVar: "MC_HEALTH_TEST,MC_OBD_TEST", Hidden: true, }, cli.DurationFlag{ Name: "deadline", - Usage: "maximum duration that OBD tests should be allowed to run", + Usage: "maximum duration that health tests should be allowed to run", Value: 3600 * time.Second, EnvVar: "MC_HEALTH_DEADLINE,MC_OBD_DEADLINE", }, @@ -55,9 +54,9 @@ var adminOBDFlags = []cli.Flag{ var adminSubnetHealthCmd = cli.Command{ Name: "health", Usage: "run health check for Subnet", - Action: mainAdminOBD, + Action: mainAdminHealth, Before: setGlobalsFromContext, - Flags: append(adminOBDFlags, globalFlags...), + Flags: append(adminHealthFlags, globalFlags...), CustomHelpTemplate: `NAME: {{.HelpName}} - {{.Usage}} @@ -73,33 +72,15 @@ EXAMPLES: `, } -type clusterOBDStruct struct { - Status string `json:"status"` - Error string `json:"error,omitempty"` - Info madmin.OBDInfo `json:"obdInfo,omitempty"` -} - -func (u clusterOBDStruct) String() string { - return u.JSON() -} - -// JSON jsonifies service status message. -func (u clusterOBDStruct) JSON() string { - statusJSONBytes, e := json.MarshalIndent(u, " ", " ") - fatalIf(probe.NewError(e), "Unable to marshal into JSON.") - - return string(statusJSONBytes) -} - // checkAdminInfoSyntax - validate arguments passed by a user -func checkAdminOBDSyntax(ctx *cli.Context) { +func checkAdminHealthSyntax(ctx *cli.Context) { if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 { cli.ShowCommandHelpAndExit(ctx, "health", 1) // last argument is exit code } } -//compress and tar obd output -func tarGZ(c clusterOBDStruct, alias string) error { +//compress and tar health report output +func tarGZ(c HealthReportInfo, alias string) error { filename := fmt.Sprintf("%s-health_%s.json.gz", filepath.Clean(alias), time.Now().Format("20060102150405")) f, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR, 0666) if err != nil { @@ -115,6 +96,19 @@ func tarGZ(c clusterOBDStruct, alias string) error { defer gzWriter.Close() enc := gojson.NewEncoder(gzWriter) + + header := HealthReportHeader{ + Subnet: Health{ + Health: SchemaVersion{ + Version: "v1", + }, + }, + } + + if err := enc.Encode(header); err != nil { + return err + } + if err := enc.Encode(c); err != nil { return err } @@ -146,8 +140,8 @@ func warnText(s string) string { return console.Colorize("WARN", s) } -func mainAdminOBD(ctx *cli.Context) error { - checkAdminOBDSyntax(ctx) +func mainAdminHealth(ctx *cli.Context) error { + checkAdminHealthSyntax(ctx) // Get the alias parameter from cli args := ctx.Args() @@ -157,12 +151,29 @@ func mainAdminOBD(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - opts := GetOBDDataTypeSlice(ctx, "test") + healthInfo, e := fetchServerHealthInfo(ctx, client) + clusterHealthInfo := MapHealthInfoToV1(healthInfo, e) + + if globalJSON { + printMsg(clusterHealthInfo) + return nil + } + + if clusterHealthInfo.GetError() != "" { + console.Println(warnText("unable to obtain health information:"), clusterHealthInfo.GetError()) + return nil + } + + return tarGZ(clusterHealthInfo, aliasedURL) +} + +func fetchServerHealthInfo(ctx *cli.Context, client *madmin.AdminClient) (madmin.HealthInfo, error) { + opts := GetHealthDataTypeSlice(ctx, "test") if len(*opts) == 0 { opts = &options } - optsMap := make(map[madmin.OBDDataType]struct{}) + optsMap := make(map[madmin.HealthDataType]struct{}) for _, opt := range *opts { optsMap[opt] = struct{}{} } @@ -214,8 +225,7 @@ func mainAdminOBD(ctx *cli.Context) error { } } } - - spinner := func(resource string, opt madmin.OBDDataType) func(bool) bool { + spinner := func(resource string, opt madmin.HealthDataType) func(bool) bool { var spinStopper func() done := false @@ -241,19 +251,17 @@ func mainAdminOBD(ctx *cli.Context) error { } } - clusterOBDInfo := clusterOBDStruct{} - - admin := spinner("Admin Info", madmin.OBDDataTypeMinioInfo) - cpu := spinner("CPU Info", madmin.OBDDataTypeSysCPU) - diskHw := spinner("Disk Info", madmin.OBDDataTypeSysDiskHw) - osInfo := spinner("OS Info", madmin.OBDDataTypeSysOsInfo) - mem := spinner("Mem Info", madmin.OBDDataTypeSysMem) - process := spinner("Process Info", madmin.OBDDataTypeSysLoad) - config := spinner("Server Config", madmin.OBDDataTypeMinioConfig) - drive := spinner("Drive Test", madmin.OBDDataTypePerfDrive) - net := spinner("Network Test", madmin.OBDDataTypePerfNet) - - progress := func(info madmin.OBDInfo) { + admin := spinner("Admin Info", madmin.HealthDataTypeMinioInfo) + cpu := spinner("CPU Info", madmin.HealthDataTypeSysCPU) + diskHw := spinner("Disk Info", madmin.HealthDataTypeSysDiskHw) + osInfo := spinner("OS Info", madmin.HealthDataTypeSysOsInfo) + mem := spinner("Mem Info", madmin.HealthDataTypeSysMem) + process := spinner("Process Info", madmin.HealthDataTypeSysLoad) + config := spinner("Server Config", madmin.HealthDataTypeMinioConfig) + drive := spinner("Drive Test", madmin.HealthDataTypePerfDrive) + net := spinner("Network Test", madmin.HealthDataTypePerfNet) + + progress := func(info madmin.HealthInfo) { _ = admin(len(info.Minio.Info.Servers) > 0) && cpu(len(info.Sys.CPUInfo) > 0) && diskHw(len(info.Sys.DiskHwInfo) > 0) && @@ -265,45 +273,33 @@ func mainAdminOBD(ctx *cli.Context) error { net(len(info.Perf.Net) > 1 && len(info.Perf.NetParallel.Addr) > 0) } + var err error + var healthInfo madmin.HealthInfo + // Fetch info of all servers (cluster or single server) - obdChan := client.ServerOBDInfo(cont, *opts, ctx.Duration("deadline")) - for adminOBDInfo := range obdChan { - if adminOBDInfo.Error != "" { - clusterOBDInfo.Status = "Error" - clusterOBDInfo.Error = adminOBDInfo.Error - clusterOBDInfo.Info.Error = "" - clusterOBDInfo.Info.Minio.Info = madmin.InfoMessage{} + obdChan := client.ServerHealthInfo(cont, *opts, ctx.Duration("deadline")) + for adminHealthInfo := range obdChan { + if adminHealthInfo.Error != "" { + err = errors.New(adminHealthInfo.Error) break } - clusterOBDInfo.Status = "Success" - clusterOBDInfo.Info = adminOBDInfo - progress(adminOBDInfo) + healthInfo = adminHealthInfo + progress(adminHealthInfo) } // cancel the context if obdChan has returned. cancel() - - if globalJSON { - printMsg(clusterOBDInfo) - return nil - } - - if clusterOBDInfo.Error != "" { - console.Println(warnText("unable to obtain health information:"), clusterOBDInfo.Error) - return nil - } - - return tarGZ(clusterOBDInfo, aliasedURL) + return healthInfo, err } -// OBDDataTypeSlice is a typed list of OBD tests -type OBDDataTypeSlice []madmin.OBDDataType +// HealthDataTypeSlice is a typed list of health tests +type HealthDataTypeSlice []madmin.HealthDataType // Set - sets the flag to the given value -func (d *OBDDataTypeSlice) Set(value string) error { +func (d *HealthDataTypeSlice) Set(value string) error { for _, v := range strings.Split(value, ",") { - if obdData, ok := madmin.OBDDataTypesMap[strings.Trim(v, " ")]; ok { + if obdData, ok := madmin.HealthDataTypesMap[strings.Trim(v, " ")]; ok { *d = append(*d, obdData) } else { return fmt.Errorf("valid options include %s", options.String()) @@ -312,8 +308,8 @@ func (d *OBDDataTypeSlice) Set(value string) error { return nil } -// String - returns the string representation of the OBD datatypes -func (d *OBDDataTypeSlice) String() string { +// String - returns the string representation of the health datatypes +func (d *HealthDataTypeSlice) String() string { val := "" for _, obdData := range *d { formatStr := "%s" @@ -328,68 +324,68 @@ func (d *OBDDataTypeSlice) String() string { } // Value - returns the value -func (d *OBDDataTypeSlice) Value() []madmin.OBDDataType { +func (d *HealthDataTypeSlice) Value() []madmin.HealthDataType { return *d } // Get - returns the value -func (d *OBDDataTypeSlice) Get() interface{} { +func (d *HealthDataTypeSlice) Get() interface{} { return *d } -// OBDDataTypeFlag is a typed flag to represent OBD datatypes -type OBDDataTypeFlag struct { +// HealthDataTypeFlag is a typed flag to represent health datatypes +type HealthDataTypeFlag struct { Name string Usage string EnvVar string Hidden bool - Value *OBDDataTypeSlice + Value *HealthDataTypeSlice } // String - returns the string to be shown in the help message -func (f OBDDataTypeFlag) String() string { +func (f HealthDataTypeFlag) String() string { return fmt.Sprintf("--%s %s", f.Name, f.Usage) } // GetName - returns the name of the flag -func (f OBDDataTypeFlag) GetName() string { +func (f HealthDataTypeFlag) GetName() string { return f.Name } -// GetOBDDataTypeSlice - returns the list of set OBD tests -func GetOBDDataTypeSlice(c *cli.Context, name string) *OBDDataTypeSlice { +// GetHealthDataTypeSlice - returns the list of set health tests +func GetHealthDataTypeSlice(c *cli.Context, name string) *HealthDataTypeSlice { generic := c.Generic(name) if generic == nil { return nil } - return generic.(*OBDDataTypeSlice) + return generic.(*HealthDataTypeSlice) } -// GetGlobalOBDDataTypeSlice - returns the list of set OBD tests set globally -func GetGlobalOBDDataTypeSlice(c *cli.Context, name string) *OBDDataTypeSlice { +// GetGlobalHealthDataTypeSlice - returns the list of set health tests set globally +func GetGlobalHealthDataTypeSlice(c *cli.Context, name string) *HealthDataTypeSlice { generic := c.GlobalGeneric(name) if generic == nil { return nil } - return generic.(*OBDDataTypeSlice) + return generic.(*HealthDataTypeSlice) } // Apply - applies the flag -func (f OBDDataTypeFlag) Apply(set *flag.FlagSet) { +func (f HealthDataTypeFlag) Apply(set *flag.FlagSet) { f.ApplyWithError(set) } // ApplyWithError - applies with error -func (f OBDDataTypeFlag) ApplyWithError(set *flag.FlagSet) error { +func (f HealthDataTypeFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) if envVal, ok := syscall.Getenv(envVar); ok { - newVal := &OBDDataTypeSlice{} + newVal := &HealthDataTypeSlice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as OBD datatype value for flag %s: %s", envVal, f.Name, err) + return fmt.Errorf("could not parse %s as health datatype value for flag %s: %s", envVal, f.Name, err) } } f.Value = newVal @@ -401,11 +397,11 @@ func (f OBDDataTypeFlag) ApplyWithError(set *flag.FlagSet) error { for _, name := range strings.Split(f.Name, ",") { name = strings.Trim(name, " ") if f.Value == nil { - f.Value = &OBDDataTypeSlice{} + f.Value = &HealthDataTypeSlice{} } set.Var(f.Value, name, f.Usage) } return nil } -var options = OBDDataTypeSlice(madmin.OBDDataTypesList) +var options = HealthDataTypeSlice(madmin.HealthDataTypesList) diff --git a/cmd/admin-subnet.go b/cmd/admin-subnet.go index 330d318d8c..7650094c3a 100644 --- a/cmd/admin-subnet.go +++ b/cmd/admin-subnet.go @@ -21,29 +21,31 @@ import ( "github.com/minio/cli" ) +var subnetHealthSubcommands = []cli.Command{ + adminSubnetHealthCmd, + // adminSubnetRegister to be added +} + var adminSubnetCmd = cli.Command{ - Name: "subnet", - Usage: "Subnet related commands", - Action: mainAdminSubnet, - Before: setGlobalsFromContext, - Flags: globalFlags, - Subcommands: []cli.Command{ - adminSubnetHealthCmd, - // adminSubnetRegister to be added - }, + Name: "subnet", + Usage: "Subnet related commands", + Action: mainAdminSubnet, + Before: setGlobalsFromContext, + Flags: globalFlags, + Subcommands: subnetHealthSubcommands, HideHelpCommand: true, } // mainAdminSubnet is the handle for "mc admin subnet" command. func mainAdminSubnet(ctx *cli.Context) error { - cli.ShowCommandHelp(ctx, ctx.Args().First()) + commandNotFound(ctx, subnetHealthSubcommands) return nil // Sub-commands like "health", "register" have their own main. } // Deprecated - to be removed in a future release // mainAdminSubnet is the handle for "mc admin subnet" command. -func mainAdminHealth(ctx *cli.Context) error { +func mainAdminOBD(ctx *cli.Context) error { color.Yellow("Deprecated - please use 'mc admin subnet health'") return nil } @@ -52,7 +54,7 @@ var adminHealthCmd = cli.Command{ Name: "health", Aliases: []string{"obd"}, Usage: "Deprecated - please use 'mc admin subnet health'", - Action: mainAdminHealth, + Action: mainAdminOBD, CustomHelpTemplate: `{{.Usage}}`, Hidden: true, } diff --git a/cmd/health.go b/cmd/health.go new file mode 100644 index 0000000000..78c779f3c1 --- /dev/null +++ b/cmd/health.go @@ -0,0 +1,46 @@ +/* + * MinIO Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package cmd + +import "time" + +// HealthReportInfo - interface to be implemented by health report schema struct +type HealthReportInfo interface { + GetTimestamp() time.Time + GetStatus() string + GetError() string + message +} + +// HealthReportHeader - Header of the subnet health report +// expected to generate JSON output of the form +// {"subnet":{"health":{"version":"v1"}}} +type HealthReportHeader struct { + Subnet Health `json:"subnet"` +} + +// Health - intermediate struct for subnet health header +// Just used to achieve the JSON structure we want +type Health struct { + Health SchemaVersion `json:"health"` +} + +// SchemaVersion - version of the health report schema +type SchemaVersion struct { + Version string `json:"version"` +} diff --git a/cmd/health_v1.go b/cmd/health_v1.go new file mode 100644 index 0000000000..a13bbce7ee --- /dev/null +++ b/cmd/health_v1.go @@ -0,0 +1,296 @@ +/* + * MinIO Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package cmd + +import ( + "encoding/json" + "reflect" + "sync" + "time" + + "github.com/minio/mc/pkg/probe" + "github.com/minio/minio-go/v7/pkg/set" + "github.com/minio/minio/pkg/madmin" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/mem" +) + +// HwServersV1 - hardware health Info +type HwServersV1 struct { + Servers []HwServerV1 `json:"servers,omitempty"` +} + +// HwServerV1 - server health Info +type HwServerV1 struct { + Addr string `json:"addr"` + CPUs []HwCPUV1 `json:"cpus,omitempty"` + Drives []HwDriveV1 `json:"drives,omitempty"` + MemInfo HwMemV1 `json:"meminfo,omitempty"` + Perf HwPerfV1 `json:"perf,omitempty"` +} + +// HwCPUV1 - CPU Info +type HwCPUV1 struct { + CPUStat []cpu.InfoStat `json:"cpu,omitempty"` + TimesStat []cpu.TimesStat `json:"time,omitempty"` + Error string `json:"error,omitempty"` +} + +// HwDriveV1 - Drive info +type HwDriveV1 struct { + Counters map[string]disk.IOCountersStat `json:"counters,omitempty"` + Partitions []madmin.PartitionStat `json:"partitions,omitempty"` + Usage []*disk.UsageStat `json:"usage,omitempty"` + Error string `json:"error,omitempty"` +} + +// HwMemV1 - Includes host virtual and swap mem information +type HwMemV1 struct { + SwapMem *mem.SwapMemoryStat `json:"swap,omitempty"` + VirtualMem *mem.VirtualMemoryStat `json:"virtualmem,omitempty"` + Error string `json:"error,omitempty"` +} + +// HwPerfV1 - hardware performance +type HwPerfV1 struct { + Net HwNetPerfV1 `json:"net,omitempty"` + Drive HwDrivePerfV1 `json:"drives,omitempty"` +} + +// HwNetPerfV1 - Network performance info +type HwNetPerfV1 struct { + Serial []madmin.NetPerfInfo `json:"serial,omitempty"` + Parallel []madmin.NetPerfInfo `json:"parallel,omitempty"` +} + +// HwDrivePerfV1 - Network performance info +type HwDrivePerfV1 struct { + Serial []madmin.DrivePerfInfo `json:"serial,omitempty"` + Parallel []madmin.DrivePerfInfo `json:"parallel,omitempty"` + Error string `json:"error,omitempty"` +} + +// SwInfoV1 - software health Info +type SwInfoV1 struct { + Minio MinioHealthInfoV1 `json:"minio,omitempty"` + OsInfo []madmin.ServerOsInfo `json:"osinfos,omitempty"` +} + +// MinioHealthInfoV1 - Health info of the MinIO cluster +type MinioHealthInfoV1 struct { + Info madmin.InfoMessage `json:"info,omitempty"` + Config interface{} `json:"config,omitempty"` + ProcInfo []madmin.ServerProcInfo `json:"procinfos,omitempty"` + Error string `json:"error,omitempty"` +} + +// ClusterHealthV1 - main struct of the health report +type ClusterHealthV1 struct { + TimeStamp time.Time `json:"timestamp,omitempty"` + Status string `json:"status"` + Error string `json:"error,omitempty"` + Hardware HwServersV1 `json:"hardware,omitempty"` + Software SwInfoV1 `json:"software,omitempty"` +} + +func (ch ClusterHealthV1) String() string { + return ch.JSON() +} + +// JSON jsonifies service status message. +func (ch ClusterHealthV1) JSON() string { + statusJSONBytes, e := json.MarshalIndent(ch, " ", " ") + fatalIf(probe.NewError(e), "Unable to marshal into JSON.") + + return string(statusJSONBytes) +} + +// GetStatus - return status of the health info +func (ch ClusterHealthV1) GetStatus() string { + return ch.Status +} + +// GetError - return error from the health info +func (ch ClusterHealthV1) GetError() string { + return ch.Error +} + +// GetTimestamp - return timestamp from the health info +func (ch ClusterHealthV1) GetTimestamp() time.Time { + return ch.TimeStamp +} + +// MapHealthInfoToV1 - maps the health info returned by minio server to V1 format +func MapHealthInfoToV1(healthInfo madmin.HealthInfo, err error) HealthReportInfo { + ch := ClusterHealthV1{} + ch.TimeStamp = healthInfo.TimeStamp + if err != nil { + ch.Status = "Error" + ch.Error = err.Error() + return ch + } + + ch.Status = "Success" + + serverAddrs := set.NewStringSet() + + var serverCPUs map[string][]HwCPUV1 + var serverDrives map[string][]HwDriveV1 + var serverMems map[string]HwMemV1 + var serverNetPerfSerial, serverNetPerfParallel map[string][]madmin.NetPerfInfo + var serverDrivePerf map[string]HwDrivePerfV1 + + mapCPUs := func() { serverCPUs = mapServerCPUs(healthInfo) } + mapDrives := func() { serverDrives = mapServerDrives(healthInfo) } + mapMems := func() { serverMems = mapServerMems(healthInfo) } + mapNetPerf := func() { serverNetPerfSerial, serverNetPerfParallel = mapServerNetPerf(healthInfo) } + mapDrivePerf := func() { serverDrivePerf = mapServerDrivePerf(healthInfo) } + + parallelize(mapCPUs, mapDrives, mapMems, mapNetPerf, mapDrivePerf) + + addKeysToSet(reflect.ValueOf(serverCPUs).MapKeys(), &serverAddrs) + addKeysToSet(reflect.ValueOf(serverDrives).MapKeys(), &serverAddrs) + addKeysToSet(reflect.ValueOf(serverMems).MapKeys(), &serverAddrs) + addKeysToSet(reflect.ValueOf(serverNetPerfSerial).MapKeys(), &serverAddrs) + serverAddrs.Add(healthInfo.Perf.NetParallel.Addr) + addKeysToSet(reflect.ValueOf(serverDrivePerf).MapKeys(), &serverAddrs) + + // Merge hardware info + hw := HwServersV1{Servers: []HwServerV1{}} + for addr := range serverAddrs { + perf := HwPerfV1{ + Net: HwNetPerfV1{ + Serial: serverNetPerfSerial[addr], + Parallel: serverNetPerfParallel[addr], + }, + Drive: serverDrivePerf[addr], + } + hw.Servers = append(hw.Servers, HwServerV1{ + Addr: addr, + CPUs: serverCPUs[addr], + Drives: serverDrives[addr], + MemInfo: serverMems[addr], + Perf: perf, + }) + } + + ch.Hardware = hw + + ch.Software = SwInfoV1{ + Minio: MinioHealthInfoV1{ + Info: healthInfo.Minio.Info, + Config: healthInfo.Minio.Config, + Error: healthInfo.Minio.Error, + ProcInfo: healthInfo.Sys.ProcInfo, + }, + OsInfo: healthInfo.Sys.OsInfo, + } + return ch +} + +func parallelize(functions ...func()) { + var waitGroup sync.WaitGroup + waitGroup.Add(len(functions)) + + defer waitGroup.Wait() + + for _, function := range functions { + go func(fn func()) { + defer waitGroup.Done() + fn() + }(function) + } +} + +func addKeysToSet(input []reflect.Value, output *set.StringSet) { + for _, key := range input { + output.Add(key.String()) + } +} + +func mapServerCPUs(healthInfo madmin.HealthInfo) map[string][]HwCPUV1 { + serverCPUs := map[string][]HwCPUV1{} + for _, ci := range healthInfo.Sys.CPUInfo { + cpus, ok := serverCPUs[ci.Addr] + if !ok { + cpus = []HwCPUV1{} + } + cpus = append(cpus, HwCPUV1{ + CPUStat: ci.CPUStat, + TimesStat: ci.TimeStat, + Error: ci.Error, + }) + serverCPUs[ci.Addr] = cpus + } + return serverCPUs +} + +func mapServerDrives(healthInfo madmin.HealthInfo) map[string][]HwDriveV1 { + serverDrives := map[string][]HwDriveV1{} + for _, di := range healthInfo.Sys.DiskHwInfo { + drives, ok := serverDrives[di.Addr] + if !ok { + drives = []HwDriveV1{} + } + drives = append(drives, HwDriveV1{ + Counters: di.Counters, + Partitions: di.Partitions, + Usage: di.Usage, + Error: di.Error, + }) + serverDrives[di.Addr] = drives + } + return serverDrives +} + +func mapServerMems(healthInfo madmin.HealthInfo) map[string]HwMemV1 { + serverMems := map[string]HwMemV1{} + for _, mi := range healthInfo.Sys.MemInfo { + serverMems[mi.Addr] = HwMemV1{ + SwapMem: mi.SwapMem, + VirtualMem: mi.VirtualMem, + Error: mi.Error, + } + } + return serverMems +} + +func mapServerNetPerf(healthInfo madmin.HealthInfo) (map[string][]madmin.NetPerfInfo, map[string][]madmin.NetPerfInfo) { + snpSerial := map[string][]madmin.NetPerfInfo{} + for _, serverPerf := range healthInfo.Perf.Net { + snpSerial[serverPerf.Addr] = serverPerf.Net + } + + snpParallel := map[string][]madmin.NetPerfInfo{} + snpParallel[healthInfo.Perf.NetParallel.Addr] = healthInfo.Perf.NetParallel.Net + + return snpSerial, snpParallel +} + +func mapServerDrivePerf(healthInfo madmin.HealthInfo) map[string]HwDrivePerfV1 { + sdp := map[string]HwDrivePerfV1{} + for _, drivePerf := range healthInfo.Perf.DriveInfo { + sdp[drivePerf.Addr] = HwDrivePerfV1{ + Serial: drivePerf.Serial, + Parallel: drivePerf.Parallel, + Error: drivePerf.Error, + } + } + return sdp +} diff --git a/go.mod b/go.mod index 4b794d80fe..0c1e592bc4 100644 --- a/go.mod +++ b/go.mod @@ -14,19 +14,17 @@ require ( github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-runewidth v0.0.9 // indirect github.com/minio/cli v1.22.0 - github.com/minio/minio v0.0.0-20201113003322-7549de034108 - github.com/minio/minio-go/v7 v7.0.6-0.20201013215222-14baba9e61ac + github.com/minio/minio v0.0.0-20201122074850-39f3d5493bc9 + github.com/minio/minio-go/v7 v7.0.6-0.20201118225257-f6869a5e2a6a github.com/minio/sha256-simd v0.1.1 github.com/mitchellh/go-homedir v1.1.0 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect - github.com/philhofer/fwd v1.1.0 // indirect github.com/pkg/profile v1.3.0 github.com/pkg/xattr v0.4.1 github.com/posener/complete v1.2.3 github.com/rjeczalik/notify v0.9.2 github.com/rs/xid v1.2.1 - github.com/tinylib/msgp v1.1.3 // indirect - github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31 // indirect + github.com/shirou/gopsutil v2.20.10-0.20201015215925-32d4603d01b7+incompatible golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee golang.org/x/net v0.0.0-20201010224723-4f7140c49acb golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb // indirect diff --git a/go.sum b/go.sum index e7dd43cad5..b62cf4ce9b 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,7 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.29.11/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= -github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M= -github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw= +github.com/bcicen/jstream v1.0.1/go.mod h1:9ielPxqFry7Y4Tg3j4BfjPocfJ3TbsRtXOAYXYmRuAQ= github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= @@ -45,8 +44,6 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98= -github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= @@ -81,7 +78,6 @@ github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -214,8 +210,6 @@ github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ github.com/klauspost/readahead v1.3.1/go.mod h1:AH9juHzNH7xqdqFHrMRSHeH2Ps+vFf+kblDqzPFiLJg= github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -250,16 +244,10 @@ github.com/minio/cli v1.22.0/go.mod h1:bYxnK0uS629N3Bq+AOZZ+6lwF77Sodk4+UL9vNuXh github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= -github.com/minio/minio v0.0.0-20201102034248-d8e07f2c41c8 h1:yCDFjUBUoE1uNr8dEqjHuwySdAtOyvVONchEVrPPOGQ= -github.com/minio/minio v0.0.0-20201102034248-d8e07f2c41c8/go.mod h1:640kMkCwiyOX8dheptHYModdUw4HrnUFHKw3McqUXD8= -github.com/minio/minio v0.0.0-20201112201209-8dd9e4d46b28 h1:vjsyaPN8PWCBML3rmUJpOdAUVfPKQnEiZm2G35qZ6wM= -github.com/minio/minio v0.0.0-20201112201209-8dd9e4d46b28/go.mod h1:EsYsmlW/6bfedkXM9altcos/rEuPsPHmsP6H5Wk+iF0= -github.com/minio/minio v0.0.0-20201113003322-7549de034108 h1:nL2u5DnH3y83GykigBKFJtNiUo4XB4ArD/fNuDmAxLg= -github.com/minio/minio v0.0.0-20201113003322-7549de034108/go.mod h1:EsYsmlW/6bfedkXM9altcos/rEuPsPHmsP6H5Wk+iF0= -github.com/minio/minio-go/v7 v7.0.6-0.20200929220449-755b5633803a h1:duFwQxzoPzBt4LbaftSVVTDwRrpuMIKI6XoJ5mKSaOs= -github.com/minio/minio-go/v7 v7.0.6-0.20200929220449-755b5633803a/go.mod h1:CSt2ETZNs+bIIhWTse0mcZKZWMGrFU7Er7RR0TmkDYk= -github.com/minio/minio-go/v7 v7.0.6-0.20201013215222-14baba9e61ac h1:0meQIZTQR/JkAxfygReKcb15QINBKpFd4LII2PT5jSY= -github.com/minio/minio-go/v7 v7.0.6-0.20201013215222-14baba9e61ac/go.mod h1:CSt2ETZNs+bIIhWTse0mcZKZWMGrFU7Er7RR0TmkDYk= +github.com/minio/minio v0.0.0-20201122074850-39f3d5493bc9 h1:WdX6LYHNgZc0XwTPknEYSi/BrTgK2kacNj1UJI+Beew= +github.com/minio/minio v0.0.0-20201122074850-39f3d5493bc9/go.mod h1:uqJmu8JpophzxppX+ZwQon8MkNq6w/Z67qqImn5cwJc= +github.com/minio/minio-go/v7 v7.0.6-0.20201118225257-f6869a5e2a6a h1:sPLqZWtSR1G57sQq/b5RDEADZ5t++JuIwBxu7NvicMY= +github.com/minio/minio-go/v7 v7.0.6-0.20201118225257-f6869a5e2a6a/go.mod h1:HcIuq+11d/3MfavIPZiswSzfQ1VJ2Lwxp/XLtW46IWQ= github.com/minio/selfupdate v0.3.1/go.mod h1:b8ThJzzH7u2MkF6PcIra7KaXO9Khf6alWPvMSyTDCFM= github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= @@ -294,6 +282,7 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/nats-io/stan.go v0.7.0/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU= github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4= github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -302,34 +291,38 @@ github.com/olivere/elastic/v7 v7.0.12/go.mod h1:14rWX28Pnh3qCKYRVnSGXWLf9MbLonYS github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/philhofer/fwd v1.1.0 h1:PAdZw9+/BCf4gc/kA2L/PbGPkFe72Kl2GLZXTG8HpU8= github.com/philhofer/fwd v1.1.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.4.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.3.0 h1:OQIvuDgm00gWVWGTf4m4mCt6W1/0YqU7Ntg0mySWgaI= github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/xattr v0.4.1 h1:dhclzL6EqOXNaPDWqoeb9tIxATfBSmjqL0b4DpSjwRw= github.com/pkg/xattr v0.4.1/go.mod h1:W2cGD0TBEus7MkUgv0tNZ9JutLtVO3cXu+IBRuHqnFs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= @@ -343,37 +336,40 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/secure-io/sio-go v0.3.0 h1:QKGb6rGJeiExac9wSWxnWPYo8O8OFN7lxXQvHshX6vo= github.com/secure-io/sio-go v0.3.0/go.mod h1:D3KmXgKETffyYxBdFRN+Hpd2WzhzqS0EQwT3XWsAcBU= -github.com/shirou/gopsutil v2.20.3-0.20200314133625-53cec6b37e6a+incompatible h1:YiKUe2ZOmfpDBH4OSyxwkx/mjNqHHnNhOtZ2mPyRme8= -github.com/shirou/gopsutil v2.20.3-0.20200314133625-53cec6b37e6a+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v2.20.10-0.20201015215925-32d4603d01b7+incompatible h1:4Nw/OaZkO6z7Tj2V48FQkGcVESBvJmKvj+SLKugM6x8= +github.com/shirou/gopsutil v2.20.10-0.20201015215925-32d4603d01b7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/gunit v1.1.3/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= -github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tinylib/msgp v1.1.3 h1:3giwAkmtaEDLSV0MdO1lDLuPgklgPzmk8H9+So2BVfA= github.com/tinylib/msgp v1.1.3/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31 h1:OXcKh35JaYsGMRzpvFkLv/MEyPuL49CThT1pZ8aSml4= -github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= @@ -381,9 +377,11 @@ github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd/v3 v3.3.0-rc.0.0.20200707003333-58bb8ae09f8e h1:HZQLoe71Q24wVyDrGBRcVuogx32U+cPlcm/WoSLUI6c= go.etcd.io/etcd/v3 v3.3.0-rc.0.0.20200707003333-58bb8ae09f8e/go.mod h1:UENlOa05tkNvLx9VnNziSerG4Ro74upGK6Apd4v6M/Y= @@ -393,6 +391,7 @@ go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= @@ -410,7 +409,6 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -419,9 +417,11 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -439,7 +439,6 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -476,7 +475,6 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200915084602-288bc346aa39 h1:356XA7ITklAU2//sYkjFeco+dH1bCRD8XCJ9FIEsvo4= golang.org/x/sys v0.0.0-20200915084602-288bc346aa39/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb h1:HS9IzC4UFbpMBLQUDSQcU+ViVT1vdFCQVjdPVpTlZrs= @@ -489,6 +487,7 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -504,10 +503,12 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f h1:7+Nz9MyPqt2qMCTvNiRy1G0zYfkB7UCa+ayT6uVvbyI= golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -537,6 +538,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -563,6 +565,8 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=