Merge pull request #334 from replicatedhq/host-preflgihts-ux

Host preflight ux improvements
This commit is contained in:
emosbaugh
2021-03-02 12:03:17 -08:00
committed by GitHub
48 changed files with 644 additions and 361 deletions
+5
View File
@@ -93,6 +93,7 @@ func runPreflights(v *viper.Viper, arg string) error {
s := spin.New()
go func() {
lastMsg := ""
for {
select {
case msg, ok := <-progressCh:
@@ -104,6 +105,10 @@ func runPreflights(v *viper.Viper, arg string) error {
c := color.New(color.FgHiRed)
c.Println(fmt.Sprintf("%s\r * %v", cursor.ClearEntireLine(), msg))
case string:
if lastMsg == msg {
break
}
lastMsg = msg
c := color.New(color.FgCyan)
c.Println(fmt.Sprintf("%s\r * %s", cursor.ClearEntireLine(), msg))
}
+23 -92
View File
@@ -1,6 +1,7 @@
package analyzer
import (
"fmt"
"strconv"
"github.com/pkg/errors"
@@ -40,100 +41,30 @@ func isExcluded(excludeVal multitype.BoolOrString) (bool, error) {
return parsed, nil
}
func HostAnalyze(hostAnalyzer *troubleshootv1beta2.HostAnalyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) {
if hostAnalyzer.CPU != nil {
result, err := analyzeHostCPU(hostAnalyzer.CPU, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.TCPLoadBalancer != nil {
result, err := analyzeHostTCPLoadBalancer(hostAnalyzer.TCPLoadBalancer, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.HTTPLoadBalancer != nil {
result, err := analyzeHostHTTPLoadBalancer(hostAnalyzer.HTTPLoadBalancer, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.DiskUsage != nil {
result, err := analyzeHostDiskUsage(hostAnalyzer.DiskUsage, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.Memory != nil {
result, err := analyzeHostMemory(hostAnalyzer.Memory, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.TCPPortStatus != nil {
result, err := analyzeHostTCPPortStatus(hostAnalyzer.TCPPortStatus, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.HTTP != nil {
result, err := analyzeHostHTTP(hostAnalyzer.HTTP, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.Time != nil {
result, err := analyzeHostTime(hostAnalyzer.Time, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.BlockDevices != nil {
result, err := analyzeHostBlockDevices(hostAnalyzer.BlockDevices, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.TCPConnect != nil {
result, err := analyzeHostTCPConnect(hostAnalyzer.TCPConnect, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.IPV4Interfaces != nil {
result, err := analyzeHostIPV4Interfaces(hostAnalyzer.IPV4Interfaces, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.FilesystemPerformance != nil {
result, err := analyzeHostFilesystemPerformance(hostAnalyzer.FilesystemPerformance, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
}
if hostAnalyzer.Certificate != nil {
result, err := analyzeHostCertificate(hostAnalyzer.Certificate, getFile)
if err != nil {
return nil, err
}
return []*AnalyzeResult{result}, nil
func HostAnalyze(hostAnalyzer *troubleshootv1beta2.HostAnalyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) []*AnalyzeResult {
analyzer, ok := GetHostAnalyzer(hostAnalyzer)
if !ok {
return NewAnalyzeResultError(analyzer, errors.New("invalid analyzer"))
}
return nil, errors.New("invalid analyzer")
isExcluded, _ := analyzer.IsExcluded()
if isExcluded {
return nil
}
result, err := analyzer.Analyze(getFile)
if err != nil {
return NewAnalyzeResultError(analyzer, errors.Wrap(err, "analyze"))
}
return []*AnalyzeResult{result}
}
func NewAnalyzeResultError(analyzer HostAnalyzer, err error) []*AnalyzeResult {
return []*AnalyzeResult{{
IsFail: true,
Title: analyzer.Title(),
Message: fmt.Sprintf("Analyzer Failed: %v", err),
}}
}
func Analyze(analyzer *troubleshootv1beta2.Analyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) {
+49
View File
@@ -0,0 +1,49 @@
package analyzer
import troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
type HostAnalyzer interface {
Title() string
IsExcluded() (bool, error)
Analyze(getFile func(string) ([]byte, error)) (*AnalyzeResult, error)
}
func GetHostAnalyzer(analyzer *troubleshootv1beta2.HostAnalyze) (HostAnalyzer, bool) {
switch {
case analyzer.CPU != nil:
return &AnalyzeHostCPU{analyzer.CPU}, true
case analyzer.Memory != nil:
return &AnalyzeHostMemory{analyzer.Memory}, true
case analyzer.TCPLoadBalancer != nil:
return &AnalyzeHostTCPLoadBalancer{analyzer.TCPLoadBalancer}, true
case analyzer.HTTPLoadBalancer != nil:
return &AnalyzeHostHTTPLoadBalancer{analyzer.HTTPLoadBalancer}, true
case analyzer.DiskUsage != nil:
return &AnalyzeHostDiskUsage{analyzer.DiskUsage}, true
case analyzer.TCPPortStatus != nil:
return &AnalyzeHostTCPPortStatus{analyzer.TCPPortStatus}, true
case analyzer.HTTP != nil:
return &AnalyzeHostHTTP{analyzer.HTTP}, true
case analyzer.Time != nil:
return &AnalyzeHostTime{analyzer.Time}, true
case analyzer.BlockDevices != nil:
return &AnalyzeHostBlockDevices{analyzer.BlockDevices}, true
case analyzer.TCPConnect != nil:
return &AnalyzeHostTCPConnect{analyzer.TCPConnect}, true
case analyzer.IPV4Interfaces != nil:
return &AnalyzeHostIPV4Interfaces{analyzer.IPV4Interfaces}, true
case analyzer.FilesystemPerformance != nil:
return &AnalyzeHostFilesystemPerformance{analyzer.FilesystemPerformance}, true
case analyzer.Certificate != nil:
return &AnalyzeHostCertificate{analyzer.Certificate}, true
default:
return nil, false
}
}
func hostAnalyzerTitleOrDefault(meta troubleshootv1beta2.AnalyzeMeta, defaultTitle string) string {
if meta.CheckName != "" {
return meta.CheckName
}
return defaultTitle
}
+16 -6
View File
@@ -12,7 +12,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostBlockDevices(hostAnalyzer *troubleshootv1beta2.BlockDevicesAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostBlockDevices struct {
hostAnalyzer *troubleshootv1beta2.BlockDevicesAnalyze
}
func (a *AnalyzeHostBlockDevices) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Block Devices")
}
func (a *AnalyzeHostBlockDevices) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostBlockDevices) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
contents, err := getCollectedFileContents("system/block_devices.json")
if err != nil {
return nil, errors.Wrap(err, "failed to get collected file")
@@ -25,11 +39,7 @@ func analyzeHostBlockDevices(hostAnalyzer *troubleshootv1beta2.BlockDevicesAnaly
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "Block Devices"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -162,7 +162,7 @@ func TestAnalyzeBlockDevices(t *testing.T) {
return b, nil
}
result, err := analyzeHostBlockDevices(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostBlockDevices{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -7,7 +7,21 @@ import (
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func analyzeHostCertificate(hostAnalyzer *troubleshootv1beta2.CertificateAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostCertificate struct {
hostAnalyzer *troubleshootv1beta2.CertificateAnalyze
}
func (a *AnalyzeHostCertificate) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Certificate Key Pair")
}
func (a *AnalyzeHostCertificate) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostCertificate) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
collectorName := hostAnalyzer.CollectorName
if collectorName == "" {
collectorName = "certificate"
@@ -21,11 +35,7 @@ func analyzeHostCertificate(hostAnalyzer *troubleshootv1beta2.CertificateAnalyze
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "Certificate Key Pair"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -320,7 +320,7 @@ func TestAnalyzeCertificate(t *testing.T) {
return []byte(test.status), nil
}
result, err := analyzeHostCertificate(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostCertificate{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -10,7 +10,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostCPU(hostAnalyzer *troubleshootv1beta2.CPUAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostCPU struct {
hostAnalyzer *troubleshootv1beta2.CPUAnalyze
}
func (a *AnalyzeHostCPU) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Number of CPUs")
}
func (a *AnalyzeHostCPU) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostCPU) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
contents, err := getCollectedFileContents("system/cpu.json")
if err != nil {
return nil, errors.Wrap(err, "failed to get collected file")
@@ -23,11 +37,7 @@ func analyzeHostCPU(hostAnalyzer *troubleshootv1beta2.CPUAnalyze, getCollectedFi
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "Number of CPUs"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+16 -6
View File
@@ -12,7 +12,21 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)
func analyzeHostDiskUsage(hostAnalyzer *troubleshootv1beta2.DiskUsageAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostDiskUsage struct {
hostAnalyzer *troubleshootv1beta2.DiskUsageAnalyze
}
func (a *AnalyzeHostDiskUsage) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, fmt.Sprintf("Disk Usage %s", a.hostAnalyzer.CollectorName))
}
func (a *AnalyzeHostDiskUsage) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostDiskUsage) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
key := collect.HostDiskUsageKey(hostAnalyzer.CollectorName)
contents, err := getCollectedFileContents(key)
if err != nil {
@@ -26,11 +40,7 @@ func analyzeHostDiskUsage(hostAnalyzer *troubleshootv1beta2.DiskUsageAnalyze, ge
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = fmt.Sprintf("Disk Usage %s", hostAnalyzer.CollectorName)
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -367,7 +367,7 @@ func TestAnalyzeHostDiskUsage(t *testing.T) {
return b, nil
}
result, err := analyzeHostDiskUsage(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostDiskUsage{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -13,7 +13,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostFilesystemPerformance(hostAnalyzer *troubleshootv1beta2.FilesystemPerformanceAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostFilesystemPerformance struct {
hostAnalyzer *troubleshootv1beta2.FilesystemPerformanceAnalyze
}
func (a *AnalyzeHostFilesystemPerformance) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Filesystem Performance")
}
func (a *AnalyzeHostFilesystemPerformance) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostFilesystemPerformance) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
collectorName := hostAnalyzer.CollectorName
if collectorName == "" {
collectorName = "filesystemPerformance"
@@ -31,11 +45,7 @@ func analyzeHostFilesystemPerformance(hostAnalyzer *troubleshootv1beta2.Filesyst
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "Filesystem Performance"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
@@ -352,7 +352,7 @@ func TestAnalyzeHostFilesystemPerformance(t *testing.T) {
return b, nil
}
result, err := analyzeHostFilesystemPerformance(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostFilesystemPerformance{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -17,7 +17,21 @@ type httpResult struct {
Response *collect.HTTPResponse
}
func analyzeHostHTTP(hostAnalyzer *troubleshootv1beta2.HTTPAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostHTTP struct {
hostAnalyzer *troubleshootv1beta2.HTTPAnalyze
}
func (a *AnalyzeHostHTTP) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "HTTP Request")
}
func (a *AnalyzeHostHTTP) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostHTTP) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
name := filepath.Join("http", "result.json")
if hostAnalyzer.CollectorName != "" {
name = filepath.Join("http", hostAnalyzer.CollectorName+".json")
@@ -34,11 +48,7 @@ func analyzeHostHTTP(hostAnalyzer *troubleshootv1beta2.HTTPAnalyze, getCollected
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "HTTP Request"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -91,7 +91,7 @@ func TestAnalyzeHostHTTP(t *testing.T) {
return b, nil
}
result, err := analyzeHostHTTP(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostHTTP{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -10,7 +10,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostHTTPLoadBalancer(hostAnalyzer *troubleshootv1beta2.HTTPLoadBalancerAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostHTTPLoadBalancer struct {
hostAnalyzer *troubleshootv1beta2.HTTPLoadBalancerAnalyze
}
func (a *AnalyzeHostHTTPLoadBalancer) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "HTTP Load Balancer")
}
func (a *AnalyzeHostHTTPLoadBalancer) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostHTTPLoadBalancer) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
collectorName := hostAnalyzer.CollectorName
if collectorName == "" {
collectorName = "httpLoadBalancer"
@@ -28,11 +42,7 @@ func analyzeHostHTTPLoadBalancer(hostAnalyzer *troubleshootv1beta2.HTTPLoadBalan
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "HTTP Load Balancer"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+16 -6
View File
@@ -11,7 +11,21 @@ import (
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func analyzeHostIPV4Interfaces(hostAnalyzer *troubleshootv1beta2.IPV4InterfacesAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostIPV4Interfaces struct {
hostAnalyzer *troubleshootv1beta2.IPV4InterfacesAnalyze
}
func (a *AnalyzeHostIPV4Interfaces) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "IPv4 Interfaces")
}
func (a *AnalyzeHostIPV4Interfaces) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostIPV4Interfaces) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
contents, err := getCollectedFileContents("system/ipv4Interfaces.json")
if err != nil {
return nil, errors.Wrap(err, "failed to get collected file")
@@ -24,11 +38,7 @@ func analyzeHostIPV4Interfaces(hostAnalyzer *troubleshootv1beta2.IPV4InterfacesA
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "IPv4 Interfaces"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -88,7 +88,7 @@ func TestAnalyzeIPV4Interfaces(t *testing.T) {
return b, nil
}
result, err := analyzeHostIPV4Interfaces(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostIPV4Interfaces{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -11,7 +11,21 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)
func analyzeHostMemory(hostAnalyzer *troubleshootv1beta2.MemoryAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostMemory struct {
hostAnalyzer *troubleshootv1beta2.MemoryAnalyze
}
func (a *AnalyzeHostMemory) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Amount of Memory")
}
func (a *AnalyzeHostMemory) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostMemory) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
contents, err := getCollectedFileContents("system/memory.json")
if err != nil {
return nil, errors.Wrap(err, "failed to get collected file")
@@ -24,11 +38,7 @@ func analyzeHostMemory(hostAnalyzer *troubleshootv1beta2.MemoryAnalyze, getColle
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "Amount of Memory"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -164,7 +164,7 @@ func TestAnalyzeHostMemory(t *testing.T) {
return b, nil
}
result, err := analyzeHostMemory(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostMemory{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -10,7 +10,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostTCPConnect(hostAnalyzer *troubleshootv1beta2.TCPConnectAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostTCPConnect struct {
hostAnalyzer *troubleshootv1beta2.TCPConnectAnalyze
}
func (a *AnalyzeHostTCPConnect) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "TCP Connection Attempt")
}
func (a *AnalyzeHostTCPConnect) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostTCPConnect) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
fullPath := path.Join("connect", fmt.Sprintf("%s.json", hostAnalyzer.CollectorName))
collected, err := getCollectedFileContents(fullPath)
@@ -24,11 +38,7 @@ func analyzeHostTCPConnect(hostAnalyzer *troubleshootv1beta2.TCPConnectAnalyze,
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "TCP Connection Attempt"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -79,7 +79,7 @@ func TestAnalyzeTCPConnect(t *testing.T) {
return b, nil
}
result, err := analyzeHostTCPConnect(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostTCPConnect{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
+16 -6
View File
@@ -10,7 +10,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostTCPLoadBalancer(hostAnalyzer *troubleshootv1beta2.TCPLoadBalancerAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostTCPLoadBalancer struct {
hostAnalyzer *troubleshootv1beta2.TCPLoadBalancerAnalyze
}
func (a *AnalyzeHostTCPLoadBalancer) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "TCP Load Balancer")
}
func (a *AnalyzeHostTCPLoadBalancer) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostTCPLoadBalancer) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
collectorName := hostAnalyzer.CollectorName
if collectorName == "" {
collectorName = "tcpLoadBalancer"
@@ -29,11 +43,7 @@ func analyzeHostTCPLoadBalancer(hostAnalyzer *troubleshootv1beta2.TCPLoadBalance
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "TCP Load Balancer"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+16 -6
View File
@@ -10,7 +10,21 @@ import (
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
func analyzeHostTCPPortStatus(hostAnalyzer *troubleshootv1beta2.TCPPortStatusAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostTCPPortStatus struct {
hostAnalyzer *troubleshootv1beta2.TCPPortStatusAnalyze
}
func (a *AnalyzeHostTCPPortStatus) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "TCP Port Status")
}
func (a *AnalyzeHostTCPPortStatus) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostTCPPortStatus) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
fullPath := path.Join("tcpPortStatus", "tcpPortStatus.json")
if hostAnalyzer.CollectorName != "" {
fullPath = path.Join("tcpPortStatus", fmt.Sprintf("%s.json", hostAnalyzer.CollectorName))
@@ -27,11 +41,7 @@ func analyzeHostTCPPortStatus(hostAnalyzer *troubleshootv1beta2.TCPPortStatusAna
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "TCP Port Status"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+16 -6
View File
@@ -17,7 +17,21 @@ const (
UnsynchronizedInactive = "unsynchronized+inactive"
)
func analyzeHostTime(hostAnalyzer *troubleshootv1beta2.TimeAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type AnalyzeHostTime struct {
hostAnalyzer *troubleshootv1beta2.TimeAnalyze
}
func (a *AnalyzeHostTime) Title() string {
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Time")
}
func (a *AnalyzeHostTime) IsExcluded() (bool, error) {
return isExcluded(a.hostAnalyzer.Exclude)
}
func (a *AnalyzeHostTime) Analyze(getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
hostAnalyzer := a.hostAnalyzer
contents, err := getCollectedFileContents("system/time.json")
if err != nil {
return nil, errors.Wrap(err, "failed to get collected file")
@@ -30,11 +44,7 @@ func analyzeHostTime(hostAnalyzer *troubleshootv1beta2.TimeAnalyze, getCollected
result := AnalyzeResult{}
title := hostAnalyzer.CheckName
if title == "" {
title = "Time"
}
result.Title = title
result.Title = a.Title()
for _, outcome := range hostAnalyzer.Outcomes {
if outcome.Fail != nil {
+1 -1
View File
@@ -219,7 +219,7 @@ func TestAnalyzeHostTime(t *testing.T) {
return b, nil
}
result, err := analyzeHostTime(test.hostAnalyzer, getCollectedFileContents)
result, err := (&AnalyzeHostTime{test.hostAnalyzer}).Analyze(getCollectedFileContents)
if test.expectErr {
req.Error(err)
} else {
@@ -1,7 +1,5 @@
package v1beta2
import "github.com/replicatedhq/troubleshoot/pkg/multitype"
type CPUAnalyze struct {
AnalyzeMeta `json:",inline" yaml:",inline"`
Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"`
@@ -100,6 +98,4 @@ type HostAnalyze struct {
FilesystemPerformance *FilesystemPerformanceAnalyze `json:"filesystemPerformance,omitempty" yaml:"filesystemPerformance,omitempty"`
Certificate *CertificateAnalyze `json:"certificate,omitempty" yaml:"certificate,omitempty"`
Exclude multitype.BoolOrString `json:"exclude,omitempty" yaml:"exclude,omitempty"`
}
@@ -103,7 +103,6 @@ type HostCollect struct {
TCPConnect *TCPConnect `json:"tcpConnect,omitempty" yaml:"tcpConnect,omitempty"`
FilesystemPerformance *FilesystemPerformance `json:"filesystemPerformance,omitempty" yaml:"filesystemPerformance,omitempty"`
Certificate *Certificate `json:"certificate,omitempty" yaml:"certificate,omitempty"`
Exclude multitype.BoolOrString `json:"exclude,omitempty" yaml:"exclude,omitempty"`
}
func (c *HostCollect) GetName() string {
+14 -1
View File
@@ -8,6 +8,7 @@ import (
"os/exec"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
type BlockDeviceInfo struct {
@@ -28,7 +29,19 @@ type BlockDeviceInfo struct {
const lsblkColumns = "NAME,KNAME,PKNAME,TYPE,MAJ:MIN,SIZE,FSTYPE,MOUNTPOINT,SERIAL,RO,RM"
const lsblkFormat = `NAME=%q KNAME=%q PKNAME=%q TYPE=%q MAJ:MIN="%d:%d" SIZE="%d" FSTYPE=%q MOUNTPOINT=%q SERIAL=%q RO="%d" RM="%d0"`
func HostBlockDevices(c *HostCollector) (map[string][]byte, error) {
type CollectHostBlockDevices struct {
hostCollector *troubleshootv1beta2.HostBlockDevices
}
func (c *CollectHostBlockDevices) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "Block Devices")
}
func (c *CollectHostBlockDevices) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostBlockDevices) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
var devices []BlockDeviceInfo
cmd := exec.Command("lsblk", "--noheadings", "--bytes", "--pairs", "-o", lsblkColumns)
+18 -4
View File
@@ -6,6 +6,8 @@ import (
"io/ioutil"
"path/filepath"
"strings"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
const KeyPairMissing = "key-pair-missing"
@@ -15,10 +17,22 @@ const KeyPairMismatch = "key-pair-mismatch"
const KeyPairInvalid = "key-pair-invalid"
const KeyPairValid = "key-pair-valid"
func HostCertificate(c *HostCollector) (map[string][]byte, error) {
type CollectHostCertificate struct {
hostCollector *troubleshootv1beta2.Certificate
}
func (c *CollectHostCertificate) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "Certificate Key Pair")
}
func (c *CollectHostCertificate) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostCertificate) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
var result = KeyPairValid
_, err := tls.LoadX509KeyPair(c.Collect.Certificate.CertificatePath, c.Collect.Certificate.KeyPath)
_, err := tls.LoadX509KeyPair(c.hostCollector.CertificatePath, c.hostCollector.KeyPath)
if err != nil {
if strings.Contains(err.Error(), "no such file") {
result = KeyPairMissing
@@ -29,7 +43,7 @@ func HostCertificate(c *HostCollector) (map[string][]byte, error) {
} else if strings.Contains(err.Error(), "private key does not match public key") {
result = KeyPairMismatch
} else if strings.Contains(err.Error(), "failed to parse private key") {
if encrypted, _ := isEncryptedKey(c.Collect.Certificate.KeyPath); encrypted {
if encrypted, _ := isEncryptedKey(c.hostCollector.KeyPath); encrypted {
result = KeyPairEncrypted
} else {
result = KeyPairInvalid
@@ -39,7 +53,7 @@ func HostCertificate(c *HostCollector) (map[string][]byte, error) {
}
}
collectorName := c.Collect.Certificate.CollectorName
collectorName := c.hostCollector.CollectorName
if collectorName == "" {
collectorName = "certificate"
}
+40 -49
View File
@@ -1,60 +1,51 @@
package collect
import (
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
type HostCollector struct {
Collect *troubleshootv1beta2.HostCollect
type HostCollector interface {
Title() string
IsExcluded() (bool, error)
Collect(progressChan chan<- interface{}) (map[string][]byte, error)
}
type HostCollectors []*HostCollector
func (c *HostCollector) RunCollectorSync() (result map[string][]byte, err error) {
defer func() {
if r := recover(); r != nil {
err = errors.Errorf("recovered rom panic: %v", r)
}
}()
if c.Collect.CPU != nil {
result, err = HostCPU(c)
} else if c.Collect.Memory != nil {
result, err = HostMemory(c)
} else if c.Collect.TCPLoadBalancer != nil {
result, err = HostTCPLoadBalancer(c)
} else if c.Collect.HTTPLoadBalancer != nil {
result, err = HostHTTPLoadBalancer(c)
} else if c.Collect.DiskUsage != nil {
result, err = HostDiskUsage(c)
} else if c.Collect.TCPPortStatus != nil {
result, err = HostTCPPortStatus(c)
} else if c.Collect.HTTP != nil {
result, err = HostHTTP(c)
} else if c.Collect.Time != nil {
result, err = HostTime(c)
} else if c.Collect.BlockDevices != nil {
result, err = HostBlockDevices(c)
} else if c.Collect.TCPConnect != nil {
result, err = HostTCPConnect(c)
} else if c.Collect.IPV4Interfaces != nil {
result, err = HostIPV4Interfaces(c)
} else if c.Collect.FilesystemPerformance != nil {
result, err = HostFilesystemPerformance(c)
} else if c.Collect.Certificate != nil {
result, err = HostCertificate(c)
} else {
err = errors.New("no spec found to run")
return
func GetHostCollector(collector *troubleshootv1beta2.HostCollect) (HostCollector, bool) {
switch {
case collector.CPU != nil:
return &CollectHostCPU{collector.CPU}, true
case collector.Memory != nil:
return &CollectHostMemory{collector.Memory}, true
case collector.TCPLoadBalancer != nil:
return &CollectHostTCPLoadBalancer{collector.TCPLoadBalancer}, true
case collector.HTTPLoadBalancer != nil:
return &CollectHostHTTPLoadBalancer{collector.HTTPLoadBalancer}, true
case collector.DiskUsage != nil:
return &CollectHostDiskUsage{collector.DiskUsage}, true
case collector.TCPPortStatus != nil:
return &CollectHostTCPPortStatus{collector.TCPPortStatus}, true
case collector.HTTP != nil:
return &CollectHostHTTP{collector.HTTP}, true
case collector.Time != nil:
return &CollectHostTime{collector.Time}, true
case collector.BlockDevices != nil:
return &CollectHostBlockDevices{collector.BlockDevices}, true
case collector.TCPConnect != nil:
return &CollectHostTCPConnect{collector.TCPConnect}, true
case collector.IPV4Interfaces != nil:
return &CollectHostIPV4Interfaces{collector.IPV4Interfaces}, true
case collector.FilesystemPerformance != nil:
return &CollectHostFilesystemPerformance{collector.FilesystemPerformance}, true
case collector.Certificate != nil:
return &CollectHostCertificate{collector.Certificate}, true
default:
return nil, false
}
if err != nil {
return
}
func hostCollectorTitleOrDefault(meta troubleshootv1beta2.HostCollectorMeta, defaultTitle string) string {
if meta.CollectorName != "" {
return meta.CollectorName
}
return
}
func (c *HostCollector) GetDisplayName() string {
return c.Collect.GetName()
return defaultTitle
}
+14 -1
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/shirou/gopsutil/cpu"
)
@@ -12,7 +13,19 @@ type CPUInfo struct {
PhysicalCount int `json:"physicalCount"`
}
func HostCPU(c *HostCollector) (map[string][]byte, error) {
type CollectHostCPU struct {
hostCollector *troubleshootv1beta2.CPU
}
func (c *CollectHostCPU) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "CPU Info")
}
func (c *CollectHostCPU) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostCPU) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
cpuInfo := CPUInfo{}
logicalCount, err := cpu.Counts(true)
+17 -4
View File
@@ -7,6 +7,7 @@ import (
"path/filepath"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/shirou/gopsutil/disk"
)
@@ -15,14 +16,26 @@ type DiskUsageInfo struct {
UsedBytes uint64 `json:"used_bytes"`
}
func HostDiskUsage(c *HostCollector) (map[string][]byte, error) {
type CollectHostDiskUsage struct {
hostCollector *troubleshootv1beta2.DiskUsage
}
func (c *CollectHostDiskUsage) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, fmt.Sprintf("Disk Usage %s", c.hostCollector.CollectorName))
}
func (c *CollectHostDiskUsage) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostDiskUsage) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
result := map[string][]byte{}
if c.Collect.DiskUsage == nil {
if c.hostCollector == nil {
return result, nil
}
pathExists, err := traverseFiletreeDirExists(c.Collect.DiskUsage.Path)
pathExists, err := traverseFiletreeDirExists(c.hostCollector.Path)
if err != nil {
return result, errors.Wrap(err, "traverse file tree")
}
@@ -39,7 +52,7 @@ func HostDiskUsage(c *HostCollector) (map[string][]byte, error) {
if err != nil {
return nil, errors.Wrap(err, "failed to marshal disk space info")
}
key := HostDiskUsageKey(c.Collect.DiskUsage.CollectorName)
key := HostDiskUsageKey(c.hostCollector.CollectorName)
result[key] = b
return result, nil
@@ -4,12 +4,30 @@ import (
"math"
"math/rand"
"time"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
type CollectHostFilesystemPerformance struct {
hostCollector *troubleshootv1beta2.FilesystemPerformance
}
func (c *CollectHostFilesystemPerformance) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "Filesystem Performance")
}
func (c *CollectHostFilesystemPerformance) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostFilesystemPerformance) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
return collectHostFilesystemPerformance(c.hostCollector)
}
type FSPerfResults struct {
Min time.Duration
Max time.Duration
@@ -1,7 +1,10 @@
package collect
import "github.com/pkg/errors"
import (
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostFilesystemPerformance(c *HostCollector) (map[string][]byte, error) {
func collectHostFilesystemPerformance(hostCollector *troubleshootv1beta2.FilesystemPerformance) (map[string][]byte, error) {
return nil, errors.New("Filesystem performance collector is only implemented for Linux")
}
@@ -12,6 +12,7 @@ import (
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"k8s.io/apimachinery/pkg/api/resource"
)
@@ -33,33 +34,33 @@ func (d Durations) Swap(i, j int) {
d[i], d[j] = d[j], d[i]
}
func HostFilesystemPerformance(c *HostCollector) (map[string][]byte, error) {
func collectHostFilesystemPerformance(hostCollector *troubleshootv1beta2.FilesystemPerformance) (map[string][]byte, error) {
var operationSize uint64 = 1024
if c.Collect.FilesystemPerformance.OperationSizeBytes != 0 {
operationSize = c.Collect.FilesystemPerformance.OperationSizeBytes
if hostCollector.OperationSizeBytes != 0 {
operationSize = hostCollector.OperationSizeBytes
}
var fileSize uint64 = 10 * 1024 * 1024
if c.Collect.FilesystemPerformance.FileSize != "" {
quantity, err := resource.ParseQuantity(c.Collect.FilesystemPerformance.FileSize)
if hostCollector.FileSize != "" {
quantity, err := resource.ParseQuantity(hostCollector.FileSize)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse fileSize %q", c.Collect.FilesystemPerformance.FileSize)
return nil, errors.Wrapf(err, "failed to parse fileSize %q", hostCollector.FileSize)
}
fileSizeInt64, ok := quantity.AsInt64()
if !ok {
return nil, errors.Wrapf(err, "failed to parse fileSize %q", c.Collect.FilesystemPerformance.FileSize)
return nil, errors.Wrapf(err, "failed to parse fileSize %q", hostCollector.FileSize)
}
fileSize = uint64(fileSizeInt64)
}
if c.Collect.FilesystemPerformance.Directory == "" {
if hostCollector.Directory == "" {
return nil, errors.New("Directory is required to collect filesystem performance info")
}
// TODO: clean up this directory if its created
if err := os.MkdirAll(c.Collect.FilesystemPerformance.Directory, 0700); err != nil {
return nil, errors.Wrapf(err, "failed to mkdir %q", c.Collect.FilesystemPerformance.Directory)
if err := os.MkdirAll(hostCollector.Directory, 0700); err != nil {
return nil, errors.Wrapf(err, "failed to mkdir %q", hostCollector.Directory)
}
filename := filepath.Join(c.Collect.FilesystemPerformance.Directory, "fsperf")
filename := filepath.Join(hostCollector.Directory, "fsperf")
f, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
@@ -92,11 +93,11 @@ func HostFilesystemPerformance(c *HostCollector) (map[string][]byte, error) {
if err != nil {
return nil, errors.Wrapf(err, "write to %s", filename)
}
if c.Collect.FilesystemPerformance.Sync {
if hostCollector.Sync {
if err := f.Sync(); err != nil {
return nil, errors.Wrapf(err, "sync %s", filename)
}
} else if c.Collect.FilesystemPerformance.Datasync {
} else if hostCollector.Datasync {
if err := syscall.Fdatasync(int(f.Fd())); err != nil {
return nil, errors.Wrapf(err, "datasync %s", filename)
}
@@ -208,7 +209,7 @@ func HostFilesystemPerformance(c *HostCollector) (map[string][]byte, error) {
fsPerf.IOPS = int(iops)
collectorName := c.Collect.FilesystemPerformance.CollectorName
collectorName := hostCollector.CollectorName
if collectorName == "" {
collectorName = "filesystemPerformance"
}
@@ -1,7 +1,10 @@
package collect
import "github.com/pkg/errors"
import (
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostFilesystemPerformance(c *HostCollector) (map[string][]byte, error) {
func collectHostFilesystemPerformance(hostCollector *troubleshootv1beta2.FilesystemPerformance) (map[string][]byte, error) {
return nil, errors.New("Filesystem performance collector is only implemented for Linux")
}
+16 -2
View File
@@ -5,10 +5,24 @@ import (
"path/filepath"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostHTTP(c *HostCollector) (map[string][]byte, error) {
httpCollector := c.Collect.HTTP
type CollectHostHTTP struct {
hostCollector *troubleshootv1beta2.HostHTTP
}
func (c *CollectHostHTTP) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "HTTP Request")
}
func (c *CollectHostHTTP) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostHTTP) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
httpCollector := c.hostCollector
var response *http.Response
var err error
+26 -12
View File
@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"path"
@@ -14,18 +13,32 @@ import (
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/debug"
"github.com/segmentio/ksuid"
)
func HostHTTPLoadBalancer(c *HostCollector) (map[string][]byte, error) {
listenAddress := fmt.Sprintf("0.0.0.0:%d", c.Collect.HTTPLoadBalancer.Port)
type CollectHostHTTPLoadBalancer struct {
hostCollector *troubleshootv1beta2.HTTPLoadBalancer
}
func (c *CollectHostHTTPLoadBalancer) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "HTTP Load Balancer")
}
func (c *CollectHostHTTPLoadBalancer) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostHTTPLoadBalancer) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
listenAddress := fmt.Sprintf("0.0.0.0:%d", c.hostCollector.Port)
timeout := 60 * time.Minute
if c.Collect.HTTPLoadBalancer.Timeout != "" {
if c.hostCollector.Timeout != "" {
var err error
timeout, err = time.ParseDuration(c.Collect.HTTPLoadBalancer.Timeout)
timeout, err = time.ParseDuration(c.hostCollector.Timeout)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse timeout %q", c.Collect.HTTPLoadBalancer.Timeout)
return nil, errors.Wrapf(err, "failed to parse timeout %q", c.hostCollector.Timeout)
}
}
@@ -79,7 +92,7 @@ func HostHTTPLoadBalancer(c *HostCollector) (map[string][]byte, error) {
networkStatus = NetworkStatusBindPermissionDenied
break
}
log.Println(err.Error())
debug.Println(err.Error())
networkStatus = NetworkStatusErrorOther
break
}
@@ -87,10 +100,11 @@ func HostHTTPLoadBalancer(c *HostCollector) (map[string][]byte, error) {
break
}
networkStatus = attemptPOST(c.Collect.HTTPLoadBalancer.Address, requestToken, responseToken)
networkStatus = attemptPOST(c.hostCollector.Address, requestToken, responseToken)
if networkStatus == NetworkStatusErrorOther || networkStatus == NetworkStatusConnectionTimeout {
time.Sleep(50 * time.Millisecond)
progressChan <- errors.Errorf("http post %s: network status %q", c.hostCollector.Address, networkStatus)
time.Sleep(time.Second)
continue
}
@@ -107,8 +121,8 @@ func HostHTTPLoadBalancer(c *HostCollector) (map[string][]byte, error) {
}
name := path.Join("httpLoadBalancer", "httpLoadBalancer.json")
if c.Collect.HTTPLoadBalancer.CollectorName != "" {
name = path.Join("httpLoadBalancer", fmt.Sprintf("%s.json", c.Collect.HTTPLoadBalancer.CollectorName))
if c.hostCollector.CollectorName != "" {
name = path.Join("httpLoadBalancer", fmt.Sprintf("%s.json", c.hostCollector.CollectorName))
}
return map[string][]byte{
@@ -137,7 +151,7 @@ func attemptPOST(address string, request []byte, response []byte) NetworkStatus
buf := bytes.NewBuffer(request)
req, err := http.NewRequestWithContext(ctx, "POST", address, buf)
if err != nil {
fmt.Println(err.Error())
debug.Println(err.Error())
return NetworkStatusErrorOther
}
+14 -1
View File
@@ -5,9 +5,22 @@ import (
"net"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostIPV4Interfaces(c *HostCollector) (map[string][]byte, error) {
type CollectHostIPV4Interfaces struct {
hostCollector *troubleshootv1beta2.IPV4Interfaces
}
func (c *CollectHostIPV4Interfaces) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "IPv4 Interfaces")
}
func (c *CollectHostIPV4Interfaces) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostIPV4Interfaces) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
var ipv4Interfaces []net.Interface
interfaces, err := net.Interfaces()
+14 -1
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/shirou/gopsutil/mem"
)
@@ -11,7 +12,19 @@ type MemoryInfo struct {
Total uint64 `json:"total"`
}
func HostMemory(c *HostCollector) (map[string][]byte, error) {
type CollectHostMemory struct {
hostCollector *troubleshootv1beta2.Memory
}
func (c *CollectHostMemory) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "Amount of Memory")
}
func (c *CollectHostMemory) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostMemory) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
memoryInfo := MemoryInfo{}
vmstat, err := mem.VirtualMemory()
+14 -12
View File
@@ -2,12 +2,12 @@ package collect
import (
"bytes"
"fmt"
"net"
"strings"
"time"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/pkg/debug"
"github.com/segmentio/ksuid"
)
@@ -26,7 +26,7 @@ type NetworkStatusResult struct {
Status NetworkStatus `json:"status"`
}
func checkTCPConnection(listenAddress string, dialAddress string, timeout time.Duration) (NetworkStatus, error) {
func checkTCPConnection(progressChan chan<- interface{}, listenAddress string, dialAddress string, timeout time.Duration) (NetworkStatus, error) {
lstn, err := net.Listen("tcp", listenAddress)
if err != nil {
if strings.Contains(err.Error(), "address already in use") {
@@ -66,7 +66,8 @@ func checkTCPConnection(listenAddress string, dialAddress string, timeout time.D
conn, err := net.DialTimeout("tcp", dialAddress, 50*time.Millisecond)
if err != nil {
if strings.Contains(err.Error(), "i/o timeout") {
time.Sleep(time.Millisecond * 50)
progressChan <- err
time.Sleep(time.Second)
continue
}
if strings.Contains(err.Error(), "connection refused") {
@@ -79,26 +80,27 @@ func checkTCPConnection(listenAddress string, dialAddress string, timeout time.D
return NetworkStatusConnected, nil
}
time.Sleep(time.Millisecond * 50)
progressChan <- errors.New("failed to verify connection to server")
time.Sleep(time.Second)
}
}
func handleTestConnection(conn net.Conn, requestToken []byte, responseToken []byte) bool {
defer func() {
if err := conn.Close(); err != nil {
fmt.Println(err.Error())
debug.Println(err.Error())
}
}()
if err := conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
fmt.Printf("Server failed to set read deadline: %v", err)
debug.Printf("Server failed to set read deadline: %v\n", err)
return false
}
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
fmt.Printf("Server failed to read: %v", err)
debug.Printf("Server failed to read: %v\n", err)
return false
}
@@ -107,12 +109,12 @@ func handleTestConnection(conn net.Conn, requestToken []byte, responseToken []by
}
if err := conn.SetWriteDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
fmt.Printf("Server failed to set write deadline: %v", err)
debug.Printf("Server failed to set write deadline: %v\n", err)
return false
}
if _, err := conn.Write(responseToken); err != nil {
fmt.Printf("Server failed to write: %v", err)
debug.Printf("Server failed to write: %v\n", err)
return false
}
@@ -122,12 +124,12 @@ func handleTestConnection(conn net.Conn, requestToken []byte, responseToken []by
func verifyConnectionToServer(conn net.Conn, requestToken []byte, responseToken []byte) bool {
defer func() {
if err := conn.Close(); err != nil {
fmt.Println(err.Error())
debug.Println(err.Error())
}
}()
if err := conn.SetWriteDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
fmt.Printf("Client failed to set write deadline: %v", err)
debug.Printf("Client failed to set write deadline: %v\n", err)
return false
}
@@ -137,7 +139,7 @@ func verifyConnectionToServer(conn net.Conn, requestToken []byte, responseToken
}
if err := conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
fmt.Printf("Client failed to set read deadline: %v", err)
debug.Printf("Client failed to set read deadline: %v\n", err)
return false
}
+19 -6
View File
@@ -9,17 +9,30 @@ import (
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostTCPConnect(c *HostCollector) (map[string][]byte, error) {
address := c.Collect.TCPConnect.Address
type CollectHostTCPConnect struct {
hostCollector *troubleshootv1beta2.TCPConnect
}
func (c *CollectHostTCPConnect) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "TCP Connection Attempt")
}
func (c *CollectHostTCPConnect) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostTCPConnect) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
address := c.hostCollector.Address
timeout := 10 * time.Second
if c.Collect.TCPConnect.Timeout != "" {
if c.hostCollector.Timeout != "" {
var err error
timeout, err = time.ParseDuration(c.Collect.TCPConnect.Timeout)
timeout, err = time.ParseDuration(c.hostCollector.Timeout)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse timeout %q", c.Collect.TCPConnect.Timeout)
return nil, errors.Wrapf(err, "failed to parse timeout %q", c.hostCollector.Timeout)
}
}
@@ -32,7 +45,7 @@ func HostTCPConnect(c *HostCollector) (map[string][]byte, error) {
return nil, errors.Wrap(err, "failed to marshal result")
}
name := path.Join("connect", fmt.Sprintf("%s.json", c.Collect.TCPConnect.CollectorName))
name := path.Join("connect", fmt.Sprintf("%s.json", c.hostCollector.CollectorName))
return map[string][]byte{
name: b,
+21 -8
View File
@@ -7,22 +7,35 @@ import (
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostTCPLoadBalancer(c *HostCollector) (map[string][]byte, error) {
listenAddress := fmt.Sprintf("0.0.0.0:%d", c.Collect.TCPLoadBalancer.Port)
dialAddress := c.Collect.TCPLoadBalancer.Address
type CollectHostTCPLoadBalancer struct {
hostCollector *troubleshootv1beta2.TCPLoadBalancer
}
func (c *CollectHostTCPLoadBalancer) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "TCP Load Balancer")
}
func (c *CollectHostTCPLoadBalancer) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostTCPLoadBalancer) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
listenAddress := fmt.Sprintf("0.0.0.0:%d", c.hostCollector.Port)
dialAddress := c.hostCollector.Address
timeout := 60 * time.Minute
if c.Collect.TCPLoadBalancer.Timeout != "" {
if c.hostCollector.Timeout != "" {
var err error
timeout, err = time.ParseDuration(c.Collect.TCPLoadBalancer.Timeout)
timeout, err = time.ParseDuration(c.hostCollector.Timeout)
if err != nil {
return nil, errors.Wrap(err, "failed to parse durection")
}
}
networkStatus, err := checkTCPConnection(listenAddress, dialAddress, timeout)
networkStatus, err := checkTCPConnection(progressChan, listenAddress, dialAddress, timeout)
if err != nil {
return nil, err
}
@@ -37,8 +50,8 @@ func HostTCPLoadBalancer(c *HostCollector) (map[string][]byte, error) {
}
name := path.Join("tcpLoadBalancer", "tcpLoadBalancer.json")
if c.Collect.TCPLoadBalancer.CollectorName != "" {
name = path.Join("tcpLoadBalancer", fmt.Sprintf("%s.json", c.Collect.TCPLoadBalancer.CollectorName))
if c.hostCollector.CollectorName != "" {
name = path.Join("tcpLoadBalancer", fmt.Sprintf("%s.json", c.hostCollector.CollectorName))
}
return map[string][]byte{
+25 -12
View File
@@ -8,22 +8,35 @@ import (
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
func HostTCPPortStatus(c *HostCollector) (map[string][]byte, error) {
dialAddress := ""
listenAddress := fmt.Sprintf("0.0.0.0:%d", c.Collect.TCPPortStatus.Port)
type CollectHostTCPPortStatus struct {
hostCollector *troubleshootv1beta2.TCPPortStatus
}
if c.Collect.TCPPortStatus.Interface != "" {
iface, err := net.InterfaceByName(c.Collect.TCPPortStatus.Interface)
func (c *CollectHostTCPPortStatus) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "TCP Port Status")
}
func (c *CollectHostTCPPortStatus) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostTCPPortStatus) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
dialAddress := ""
listenAddress := fmt.Sprintf("0.0.0.0:%d", c.hostCollector.Port)
if c.hostCollector.Interface != "" {
iface, err := net.InterfaceByName(c.hostCollector.Interface)
if err != nil {
return nil, errors.Wrapf(err, "lookup interface %s", c.Collect.TCPPortStatus.Interface)
return nil, errors.Wrapf(err, "lookup interface %s", c.hostCollector.Interface)
}
ip, err := getIPv4FromInterface(iface)
if err != nil {
return nil, errors.Wrapf(err, "get ipv4 address for interface %s", c.Collect.TCPPortStatus.Interface)
return nil, errors.Wrapf(err, "get ipv4 address for interface %s", c.hostCollector.Interface)
}
listenAddress = fmt.Sprintf("%s:%d", ip, c.Collect.TCPPortStatus.Port)
listenAddress = fmt.Sprintf("%s:%d", ip, c.hostCollector.Port)
dialAddress = listenAddress
}
@@ -32,10 +45,10 @@ func HostTCPPortStatus(c *HostCollector) (map[string][]byte, error) {
if err != nil {
return nil, err
}
dialAddress = fmt.Sprintf("%s:%d", ip, c.Collect.TCPPortStatus.Port)
dialAddress = fmt.Sprintf("%s:%d", ip, c.hostCollector.Port)
}
networkStatus, err := checkTCPConnection(listenAddress, dialAddress, 10*time.Second)
networkStatus, err := checkTCPConnection(progressChan, listenAddress, dialAddress, 10*time.Second)
if err != nil {
return nil, err
}
@@ -49,8 +62,8 @@ func HostTCPPortStatus(c *HostCollector) (map[string][]byte, error) {
}
name := path.Join("tcpPortStatus", "tcpPortStatus.json")
if c.Collect.TCPPortStatus.CollectorName != "" {
name = path.Join("tcpPortStatus", fmt.Sprintf("%s.json", c.Collect.TCPPortStatus.CollectorName))
if c.hostCollector.CollectorName != "" {
name = path.Join("tcpPortStatus", fmt.Sprintf("%s.json", c.hostCollector.CollectorName))
}
return map[string][]byte{
name: b,
+14 -1
View File
@@ -8,6 +8,7 @@ import (
"github.com/godbus/dbus"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
)
type NTPStatus string
@@ -18,7 +19,19 @@ type TimeInfo struct {
NTPActive bool `json:"ntp_active"`
}
func HostTime(c *HostCollector) (map[string][]byte, error) {
type CollectHostTime struct {
hostCollector *troubleshootv1beta2.HostTime
}
func (c *CollectHostTime) Title() string {
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "TCP Port Status")
}
func (c *CollectHostTime) IsExcluded() (bool, error) {
return isExcluded(c.hostCollector.Exclude)
}
func (c *CollectHostTime) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
timeInfo := TimeInfo{}
conn, err := dbus.SystemBus()
+28
View File
@@ -0,0 +1,28 @@
package debug
import (
"log"
"os"
"github.com/spf13/viper"
)
var logger = log.New(os.Stderr, "[debug]", log.Lshortfile)
func Print(v ...interface{}) {
if viper.GetBool("debug") {
log.Print(v...)
}
}
func Printf(format string, v ...interface{}) {
if viper.GetBool("debug") {
log.Printf(format, v...)
}
}
func Println(v ...interface{}) {
if viper.GetBool("debug") {
log.Println(v...)
}
}
+2 -37
View File
@@ -3,13 +3,10 @@ package preflight
import (
"fmt"
"path/filepath"
"strconv"
"strings"
"github.com/pkg/errors"
analyze "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/multitype"
)
// Analyze runs the analyze phase of preflight checks
@@ -67,40 +64,8 @@ func doAnalyze(allCollectedData map[string][]byte, analyzers []*troubleshootv1be
}
for _, hostAnalyzer := range hostAnalyzers {
if excluded, _ := isExcluded(hostAnalyzer.Exclude); excluded {
continue
}
analyzeResult, err := analyze.HostAnalyze(hostAnalyzer, getCollectedFileContents, getChildCollectedFileContents)
if err != nil {
analyzeResult = []*analyze.AnalyzeResult{
{
IsFail: true,
Title: "Analyzer Failed",
Message: err.Error(),
},
}
}
if analyzeResult != nil {
analyzeResults = append(analyzeResults, analyzeResult...)
}
analyzeResult := analyze.HostAnalyze(hostAnalyzer, getCollectedFileContents, getChildCollectedFileContents)
analyzeResults = append(analyzeResults, analyzeResult...)
}
return analyzeResults
}
func isExcluded(excludeVal multitype.BoolOrString) (bool, error) {
if excludeVal.Type == multitype.Bool {
return excludeVal.BoolVal, nil
}
if excludeVal.StrVal == "" {
return false, nil
}
parsed, err := strconv.ParseBool(excludeVal.StrVal)
if err != nil {
return false, errors.Wrap(err, "failed to parse bool string")
}
return parsed, nil
}
+11 -8
View File
@@ -36,7 +36,7 @@ func (cr ClusterCollectResult) IsRBACAllowed() bool {
type HostCollectResult struct {
AllCollectedData map[string][]byte
Collectors collect.HostCollectors
Collectors []collect.HostCollector
Spec *troubleshootv1beta2.HostPreflight
}
@@ -53,12 +53,12 @@ func CollectHost(opts CollectOpts, p *troubleshootv1beta2.HostPreflight) (Collec
allCollectedData := make(map[string][]byte)
var collectors collect.HostCollectors
var collectors []collect.HostCollector
for _, desiredCollector := range collectSpecs {
collector := collect.HostCollector{
Collect: desiredCollector,
collector, ok := collect.GetHostCollector(desiredCollector)
if ok {
collectors = append(collectors, collector)
}
collectors = append(collectors, &collector)
}
collectResult := HostCollectResult{
@@ -67,12 +67,15 @@ func CollectHost(opts CollectOpts, p *troubleshootv1beta2.HostPreflight) (Collec
}
for _, collector := range collectors {
if excluded, _ := isExcluded(collector.Collect.Exclude); excluded {
isExcluded, _ := collector.IsExcluded()
if isExcluded {
continue
}
result, err := collector.RunCollectorSync()
opts.ProgressChan <- fmt.Sprintf("[%s] Running collector...", collector.Title())
result, err := collector.Collect(opts.ProgressChan)
if err != nil {
opts.ProgressChan <- errors.Errorf("failed to run collector: %s: %v\n", collector.GetDisplayName(), err)
opts.ProgressChan <- errors.Errorf("failed to run collector: %s: %v", collector.Title(), err)
continue
}