Repository: replicatedhq/troubleshoot
Pull request #333 (2021-03-01 22:46:17)

Host preflights move exclude duplicated, use meta


Patch:
diff --git a/pkg/analyze/analyzer.go b/pkg/analyze/analyzer.go
index 81acb94c..84f947ae 100644
--- a/pkg/analyze/analyzer.go
+++ b/pkg/analyze/analyzer.go
@@ -1,6 +1,7 @@
 package analyzer
 
 import (
+	"fmt"
 	"strconv"
 
 	"github.com/pkg/errors"
@@ -40,100 +41,32 @@ 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
+func HostAnalyze(hostAnalyzer *troubleshootv1beta2.HostAnalyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) []*AnalyzeResult {
+	analyzer, ok := GetHostAnalyzer(hostAnalyzer)
+	if !ok {
+		return NewAnalyzeResultError(analyzer, errors.New("invalid analyzer"))
 	}
-	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
+
+	isExcluded, err := analyzer.IsExcluded()
+	if err != nil {
+		return NewAnalyzeResultError(analyzer, errors.Wrap(err, "is excluded"))
+	} else if isExcluded {
+		return nil
 	}
-	if hostAnalyzer.Certificate != nil {
-		result, err := analyzeHostCertificate(hostAnalyzer.Certificate, getFile)
-		if err != nil {
-			return nil, err
-		}
-		return []*AnalyzeResult{result}, nil
+
+	result, err := analyzer.Analyze(getFile)
+	if err != nil {
+		return NewAnalyzeResultError(analyzer, errors.Wrap(err, "analyze"))
 	}
+	return []*AnalyzeResult{result}
+}
 
-	return nil, errors.New("invalid analyzer")
+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) {
diff --git a/pkg/analyze/host_analyzer.go b/pkg/analyze/host_analyzer.go
new file mode 100644
index 00000000..bf2292d2
--- /dev/null
+++ b/pkg/analyze/host_analyzer.go
@@ -0,0 +1,47 @@
+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.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.Memory != nil:
+		return &AnalyzeHostMemory{analyzer.Memory}, true
+	case analyzer.TCPPortStatus != nil:
+		return &AnalyzeHostTCPPortStatus{analyzer.TCPPortStatus}, true
+	case analyzer.HTTP != nil:
+		return &AnalyzeHostHTTP{analyzer.HTTP}, 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
+}
diff --git a/pkg/analyze/host_block_devices.go b/pkg/analyze/host_block_devices.go
index c4b5fca8..099c88b2 100644
--- a/pkg/analyze/host_block_devices.go
+++ b/pkg/analyze/host_block_devices.go
@@ -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 {
diff --git a/pkg/analyze/host_certificate.go b/pkg/analyze/host_certificate.go
index a31a79be..25efb64c 100644
--- a/pkg/analyze/host_certificate.go
+++ b/pkg/analyze/host_certificate.go
@@ -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 {
diff --git a/pkg/analyze/host_cpu.go b/pkg/analyze/host_cpu.go
index ba315cb6..43ec4e02 100644
--- a/pkg/analyze/host_cpu.go
+++ b/pkg/analyze/host_cpu.go
@@ -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 {
diff --git a/pkg/analyze/host_disk_usage.go b/pkg/analyze/host_disk_usage.go
index 29889fdf..a447c740 100644
--- a/pkg/analyze/host_disk_usage.go
+++ b/pkg/analyze/host_disk_usage.go
@@ -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 {
diff --git a/pkg/analyze/host_filesystem_performance.go b/pkg/analyze/host_filesystem_performance.go
index 95bc59bb..824b42bb 100644
--- a/pkg/analyze/host_filesystem_performance.go
+++ b/pkg/analyze/host_filesystem_performance.go
@@ -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 {
diff --git a/pkg/analyze/host_http.go b/pkg/analyze/host_http.go
index b07a7b73..bd44cff2 100644
--- a/pkg/analyze/host_http.go
+++ b/pkg/analyze/host_http.go
@@ -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 {
diff --git a/pkg/analyze/host_httploadbalancer.go b/pkg/analyze/host_httploadbalancer.go
index ad2ba771..9b16868e 100644
--- a/pkg/analyze/host_httploadbalancer.go
+++ b/pkg/analyze/host_httploadbalancer.go
@@ -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 {
diff --git a/pkg/analyze/host_ipv4interfaces.go b/pkg/analyze/host_ipv4interfaces.go
index 4c08a763..b855c56d 100644
--- a/pkg/analyze/host_ipv4interfaces.go
+++ b/pkg/analyze/host_ipv4interfaces.go
@@ -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 {
diff --git a/pkg/analyze/host_memory.go b/pkg/analyze/host_memory.go
index 12d57b11..1ae99ba7 100644
--- a/pkg/analyze/host_memory.go
+++ b/pkg/analyze/host_memory.go
@@ -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 {
diff --git a/pkg/analyze/host_tcp_connect.go b/pkg/analyze/host_tcp_connect.go
index 327dc0db..8baa77e4 100644
--- a/pkg/analyze/host_tcp_connect.go
+++ b/pkg/analyze/host_tcp_connect.go
@@ -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 {
diff --git a/pkg/analyze/host_tcploadbalancer.go b/pkg/analyze/host_tcploadbalancer.go
index e6efc102..702b24cd 100644
--- a/pkg/analyze/host_tcploadbalancer.go
+++ b/pkg/analyze/host_tcploadbalancer.go
@@ -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 {
diff --git a/pkg/analyze/host_tcpportstatus.go b/pkg/analyze/host_tcpportstatus.go
index 4d03b1fd..62047288 100644
--- a/pkg/analyze/host_tcpportstatus.go
+++ b/pkg/analyze/host_tcpportstatus.go
@@ -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 {
diff --git a/pkg/analyze/host_time.go b/pkg/analyze/host_time.go
index a4085776..329da374 100644
--- a/pkg/analyze/host_time.go
+++ b/pkg/analyze/host_time.go
@@ -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 {
diff --git a/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go b/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go
index 5f23e8ac..c4b06a6f 100644
--- a/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go
+++ b/pkg/apis/troubleshoot/v1beta2/hostanalyzer_shared.go
@@ -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"`
 }
diff --git a/pkg/apis/troubleshoot/v1beta2/hostcollector_shared.go b/pkg/apis/troubleshoot/v1beta2/hostcollector_shared.go
index 0e20ba53..65dd2aea 100644
--- a/pkg/apis/troubleshoot/v1beta2/hostcollector_shared.go
+++ b/pkg/apis/troubleshoot/v1beta2/hostcollector_shared.go
@@ -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 {
diff --git a/pkg/collect/host_collector.go b/pkg/collect/host_collector.go
index a28fb0e8..fddf0fcd 100644
--- a/pkg/collect/host_collector.go
+++ b/pkg/collect/host_collector.go
@@ -3,6 +3,7 @@ package collect
 import (
 	"github.com/pkg/errors"
 	troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
+	"github.com/replicatedhq/troubleshoot/pkg/multitype"
 )
 
 type HostCollector struct {
@@ -18,6 +19,10 @@ func (c *HostCollector) RunCollectorSync() (result map[string][]byte, err error)
 		}
 	}()
 
+	if c.IsExcluded() {
+		return
+	}
+
 	if c.Collect.CPU != nil {
 		result, err = HostCPU(c)
 	} else if c.Collect.Memory != nil {
@@ -55,6 +60,45 @@ func (c *HostCollector) RunCollectorSync() (result map[string][]byte, err error)
 	return
 }
 
+func (c *HostCollector) IsExcluded() bool {
+	exclude := multitype.BoolOrString{}
+	if c.Collect.CPU != nil {
+		exclude = c.Collect.CPU.Exclude
+	} else if c.Collect.Memory != nil {
+		exclude = c.Collect.Memory.Exclude
+	} else if c.Collect.TCPLoadBalancer != nil {
+		exclude = c.Collect.TCPLoadBalancer.Exclude
+	} else if c.Collect.HTTPLoadBalancer != nil {
+		exclude = c.Collect.HTTPLoadBalancer.Exclude
+	} else if c.Collect.DiskUsage != nil {
+		exclude = c.Collect.DiskUsage.Exclude
+	} else if c.Collect.TCPPortStatus != nil {
+		exclude = c.Collect.TCPPortStatus.Exclude
+	} else if c.Collect.HTTP != nil {
+		exclude = c.Collect.HTTP.Exclude
+	} else if c.Collect.Time != nil {
+		exclude = c.Collect.Time.Exclude
+	} else if c.Collect.BlockDevices != nil {
+		exclude = c.Collect.BlockDevices.Exclude
+	} else if c.Collect.TCPConnect != nil {
+		exclude = c.Collect.TCPConnect.Exclude
+	} else if c.Collect.IPV4Interfaces != nil {
+		exclude = c.Collect.IPV4Interfaces.Exclude
+	} else if c.Collect.FilesystemPerformance != nil {
+		exclude = c.Collect.FilesystemPerformance.Exclude
+	} else if c.Collect.Certificate != nil {
+		exclude = c.Collect.Certificate.Exclude
+	} else {
+		return true
+	}
+
+	isExcludedResult, err := isExcluded(exclude)
+	if err != nil {
+		return true
+	}
+	return isExcludedResult
+}
+
 func (c *HostCollector) GetDisplayName() string {
 	return c.Collect.GetName()
 }
diff --git a/pkg/preflight/analyze.go b/pkg/preflight/analyze.go
index c0d3dbae..877d9a64 100644
--- a/pkg/preflight/analyze.go
+++ b/pkg/preflight/analyze.go
@@ -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
-}
diff --git a/pkg/preflight/collect.go b/pkg/preflight/collect.go
index 5d7900cf..13f4bce0 100644
--- a/pkg/preflight/collect.go
+++ b/pkg/preflight/collect.go
@@ -67,9 +67,6 @@ func CollectHost(opts CollectOpts, p *troubleshootv1beta2.HostPreflight) (Collec
 	}
 
 	for _, collector := range collectors {
-		if excluded, _ := isExcluded(collector.Collect.Exclude); excluded {
-			continue
-		}
 		result, err := collector.RunCollectorSync()
 		if err != nil {
 			opts.ProgressChan <- errors.Errorf("failed to run collector: %s: %v\n", collector.GetDisplayName(), err)


Test patch:
diff --git a/pkg/analyze/host_block_devices_test.go b/pkg/analyze/host_block_devices_test.go
index 09e8fd3f..962b96b5 100644
--- a/pkg/analyze/host_block_devices_test.go
+++ b/pkg/analyze/host_block_devices_test.go
@@ -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 {
diff --git a/pkg/analyze/host_certificate_test.go b/pkg/analyze/host_certificate_test.go
index d7a00144..f1fb9854 100644
--- a/pkg/analyze/host_certificate_test.go
+++ b/pkg/analyze/host_certificate_test.go
@@ -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 {
diff --git a/pkg/analyze/host_disk_usage_test.go b/pkg/analyze/host_disk_usage_test.go
index 7e734fac..5bd9e1a0 100644
--- a/pkg/analyze/host_disk_usage_test.go
+++ b/pkg/analyze/host_disk_usage_test.go
@@ -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 {
diff --git a/pkg/analyze/host_filesystem_performance_test.go b/pkg/analyze/host_filesystem_performance_test.go
index 60582503..a885f473 100644
--- a/pkg/analyze/host_filesystem_performance_test.go
+++ b/pkg/analyze/host_filesystem_performance_test.go
@@ -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 {
diff --git a/pkg/analyze/host_http_test.go b/pkg/analyze/host_http_test.go
index e24461b4..0190db73 100644
--- a/pkg/analyze/host_http_test.go
+++ b/pkg/analyze/host_http_test.go
@@ -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 {
diff --git a/pkg/analyze/host_ipv4interfaces_test.go b/pkg/analyze/host_ipv4interfaces_test.go
index ed4ee0d2..65bebded 100644
--- a/pkg/analyze/host_ipv4interfaces_test.go
+++ b/pkg/analyze/host_ipv4interfaces_test.go
@@ -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 {
diff --git a/pkg/analyze/host_memory_test.go b/pkg/analyze/host_memory_test.go
index a0b70ccf..898ae0b1 100644
--- a/pkg/analyze/host_memory_test.go
+++ b/pkg/analyze/host_memory_test.go
@@ -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 {
diff --git a/pkg/analyze/host_tcp_connect_test.go b/pkg/analyze/host_tcp_connect_test.go
index 6cc8064c..04b07263 100644
--- a/pkg/analyze/host_tcp_connect_test.go
+++ b/pkg/analyze/host_tcp_connect_test.go
@@ -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 {
diff --git a/pkg/analyze/host_time_test.go b/pkg/analyze/host_time_test.go
index 63bc9deb..10c5ca62 100644
--- a/pkg/analyze/host_time_test.go
+++ b/pkg/analyze/host_time_test.go
@@ -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 {