From f108c3ca570d761f710ee0d61b29ea1e4a98701f Mon Sep 17 00:00:00 2001 From: divolgin Date: Tue, 26 Oct 2021 21:36:27 +0000 Subject: [PATCH] Analyze all deployments in all namespaces --- pkg/analyze/analyzer.go | 4 +- pkg/analyze/deployment_status.go | 96 +++++++++++++++++++++------ pkg/analyze/deployment_status_test.go | 62 +++++++++-------- 3 files changed, 112 insertions(+), 50 deletions(-) diff --git a/pkg/analyze/analyzer.go b/pkg/analyze/analyzer.go index e4fbbe19..b7088a7a 100644 --- a/pkg/analyze/analyzer.go +++ b/pkg/analyze/analyzer.go @@ -185,11 +185,11 @@ func Analyze(analyzer *troubleshootv1beta2.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - result, err := analyzeDeploymentStatus(analyzer.DeploymentStatus, getFile) + results, err := analyzeDeploymentStatus(analyzer.DeploymentStatus, findFiles) if err != nil { return nil, err } - return []*AnalyzeResult{result}, nil + return results, nil } if analyzer.StatefulsetStatus != nil { isExcluded, err := isExcluded(analyzer.StatefulsetStatus.Exclude) diff --git a/pkg/analyze/deployment_status.go b/pkg/analyze/deployment_status.go index c013d8a4..1266a498 100644 --- a/pkg/analyze/deployment_status.go +++ b/pkg/analyze/deployment_status.go @@ -10,34 +10,90 @@ import ( appsv1 "k8s.io/api/apps/v1" ) -func analyzeDeploymentStatus(analyzer *troubleshootv1beta2.DeploymentStatus, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) { - collected, err := getCollectedFileContents(filepath.Join("cluster-resources", "deployments", fmt.Sprintf("%s.json", analyzer.Namespace))) +func analyzeDeploymentStatus(analyzer *troubleshootv1beta2.DeploymentStatus, getFileContents func(string) (map[string][]byte, error)) ([]*AnalyzeResult, error) { + if analyzer.Name == "" { + return analyzeAllDeploymentStatuses(analyzer, getFileContents) + } else { + return analyzeOneDeploymentStatus(analyzer, getFileContents) + } +} + +func analyzeOneDeploymentStatus(analyzer *troubleshootv1beta2.DeploymentStatus, getFileContents func(string) (map[string][]byte, error)) ([]*AnalyzeResult, error) { + files, err := getFileContents(filepath.Join("cluster-resources", "deployments", fmt.Sprintf("%s.json", analyzer.Namespace))) if err != nil { return nil, errors.Wrap(err, "failed to read collected deployments from namespace") } - var deployments []appsv1.Deployment - if err := json.Unmarshal(collected, &deployments); err != nil { - return nil, errors.Wrap(err, "failed to unmarshal deployment list") - } + var result *AnalyzeResult + for _, collected := range files { // only 1 file here + var deployments []appsv1.Deployment + if err := json.Unmarshal(collected, &deployments); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal deployment list") + } - var status *appsv1.DeploymentStatus - for _, deployment := range deployments { - if deployment.Name == analyzer.Name { - status = deployment.Status.DeepCopy() + var status *appsv1.DeploymentStatus + for _, deployment := range deployments { + if deployment.Name == analyzer.Name { + status = deployment.Status.DeepCopy() + } + } + + if status == nil { + // there's not an error, but maybe the requested deployment is not even deployed + result = &AnalyzeResult{ + Title: fmt.Sprintf("%s Deployment Status", analyzer.Name), + IconKey: "kubernetes_deployment_status", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + IsFail: true, + Message: fmt.Sprintf("The deployment %q was not found", analyzer.Name), + } + } else { + result, err = commonStatus(analyzer.Outcomes, fmt.Sprintf("%s Status", analyzer.Name), "kubernetes_deployment_status", "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", int(status.ReadyReplicas)) + if err != nil { + return nil, errors.Wrap(err, "failed to process status") + } } } - if status == nil { - // there's not an error, but maybe the requested deployment is not even deployed - return &AnalyzeResult{ - Title: fmt.Sprintf("%s Deployment Status", analyzer.Name), - IconKey: "kubernetes_deployment_status", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", - IsFail: true, - Message: fmt.Sprintf("The deployment %q was not found", analyzer.Name), - }, nil + return []*AnalyzeResult{result}, nil +} + +func analyzeAllDeploymentStatuses(analyzer *troubleshootv1beta2.DeploymentStatus, getFileContents func(string) (map[string][]byte, error)) ([]*AnalyzeResult, error) { + var fileName string + if analyzer.Namespace != "" { + fileName = filepath.Join("cluster-resources", "deployments", fmt.Sprintf("%s.json", analyzer.Namespace)) + } else { + fileName = filepath.Join("cluster-resources", "deployments", "*.json") } - return commonStatus(analyzer.Outcomes, fmt.Sprintf("%s Status", analyzer.Name), "kubernetes_deployment_status", "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", int(status.ReadyReplicas)) + files, err := getFileContents(fileName) + if err != nil { + return nil, errors.Wrap(err, "failed to read collected deployments from file") + } + + results := []*AnalyzeResult{} + for _, collected := range files { + var deployments []appsv1.Deployment + if err := json.Unmarshal(collected, &deployments); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal deployment list") + } + + for _, deployment := range deployments { + if deployment.Status.Replicas == deployment.Status.AvailableReplicas { + continue + } + + result := &AnalyzeResult{ + Title: fmt.Sprintf("%s/%s Deployment Status", deployment.Namespace, deployment.Name), + IconKey: "kubernetes_deployment_status", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + IsFail: true, + Message: fmt.Sprintf("The deployment %s/%s has %d/%d replicas", deployment.Namespace, deployment.Name, deployment.Status.ReadyReplicas, deployment.Status.Replicas), + } + + results = append(results, result) + } + } + + return results, nil } diff --git a/pkg/analyze/deployment_status_test.go b/pkg/analyze/deployment_status_test.go index 34fedafc..087e11b4 100644 --- a/pkg/analyze/deployment_status_test.go +++ b/pkg/analyze/deployment_status_test.go @@ -12,7 +12,7 @@ func Test_deploymentStatus(t *testing.T) { tests := []struct { name string analyzer troubleshootv1beta2.DeploymentStatus - expectResult AnalyzeResult + expectResult []*AnalyzeResult files map[string][]byte }{ { @@ -34,14 +34,16 @@ func Test_deploymentStatus(t *testing.T) { Namespace: "default", Name: "kotsadm-api", }, - expectResult: AnalyzeResult{ - IsPass: true, - IsWarn: false, - IsFail: false, - Title: "kotsadm-api Status", - Message: "pass", - IconKey: "kubernetes_deployment_status", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + expectResult: []*AnalyzeResult{ + { + IsPass: true, + IsWarn: false, + IsFail: false, + Title: "kotsadm-api Status", + Message: "pass", + IconKey: "kubernetes_deployment_status", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + }, }, files: map[string][]byte{ "cluster-resources/deployments/default.json": []byte(collectedDeployments), @@ -66,14 +68,16 @@ func Test_deploymentStatus(t *testing.T) { Namespace: "default", Name: "kotsadm-api", }, - expectResult: AnalyzeResult{ - IsPass: false, - IsWarn: false, - IsFail: true, - Title: "kotsadm-api Status", - Message: "fail", - IconKey: "kubernetes_deployment_status", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + expectResult: []*AnalyzeResult{ + { + IsPass: false, + IsWarn: false, + IsFail: true, + Title: "kotsadm-api Status", + Message: "fail", + IconKey: "kubernetes_deployment_status", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + }, }, files: map[string][]byte{ "cluster-resources/deployments/default.json": []byte(collectedDeployments), @@ -104,14 +108,16 @@ func Test_deploymentStatus(t *testing.T) { Namespace: "default", Name: "kotsadm-api", }, - expectResult: AnalyzeResult{ - IsPass: false, - IsWarn: true, - IsFail: false, - Title: "kotsadm-api Status", - Message: "warn", - IconKey: "kubernetes_deployment_status", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + expectResult: []*AnalyzeResult{ + { + IsPass: false, + IsWarn: true, + IsFail: false, + Title: "kotsadm-api Status", + Message: "warn", + IconKey: "kubernetes_deployment_status", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/deployment-status.svg?w=17&h=17", + }, }, files: map[string][]byte{ "cluster-resources/deployments/default.json": []byte(collectedDeployments), @@ -123,14 +129,14 @@ func Test_deploymentStatus(t *testing.T) { t.Run(test.name, func(t *testing.T) { req := require.New(t) - getFiles := func(n string) ([]byte, error) { - return test.files[n], nil + getFiles := func(n string) (map[string][]byte, error) { + return test.files, nil } actual, err := analyzeDeploymentStatus(&test.analyzer, getFiles) req.NoError(err) - assert.Equal(t, &test.expectResult, actual) + assert.Equal(t, test.expectResult, actual) }) }