Repository: FairwindsOps/polaris
Pull request #563 (2021-06-21 14:50:17)

fix score when onlyOutputFailed is true


Patch:
diff --git a/cmd/polaris/audit.go b/cmd/polaris/audit.go
index b58b5b99..721c1f40 100644
--- a/cmd/polaris/audit.go
+++ b/cmd/polaris/audit.go
@@ -24,7 +24,6 @@ import (
 	"os"
 	"os/exec"
 
-	conf "github.com/fairwindsops/polaris/pkg/config"
 	"github.com/fairwindsops/polaris/pkg/kube"
 	"github.com/fairwindsops/polaris/pkg/validator"
 	"github.com/sirupsen/logrus"
@@ -76,7 +75,19 @@ var auditCmd = &cobra.Command{
 			}
 		}
 
-		auditData := runAndReportAudit(cmd.Context(), config, auditPath, resourceToAudit, auditOutputFile, auditOutputURL, auditOutputFormat, useColor)
+		k, err := kube.CreateResourceProvider(context.TODO(), auditPath, resourceToAudit, config)
+		if err != nil {
+			logrus.Errorf("Error fetching Kubernetes resources %v", err)
+			os.Exit(1)
+		}
+
+		auditData, err := validator.RunAudit(config, k)
+		if err != nil {
+			logrus.Errorf("Error while running audit on resources: %v", err)
+			os.Exit(1)
+		}
+
+		outputAudit(auditData, auditOutputFile, auditOutputURL, auditOutputFormat, useColor, onlyShowFailedTests)
 
 		summary := auditData.GetSummary()
 		score := summary.GetScore()
@@ -123,26 +134,17 @@ func ProcessHelmTemplates(helmChart string) (string, error) {
 	return dir, nil
 }
 
-func runAndReportAudit(ctx context.Context, c conf.Configuration, auditPath, workload, outputFile, outputURL, outputFormat string, useColor bool) validator.AuditData {
-	// Create a kubernetes client resource provider
-	k, err := kube.CreateResourceProvider(ctx, auditPath, workload, c)
-	if err != nil {
-		logrus.Errorf("Error fetching Kubernetes resources %v", err)
-		os.Exit(1)
+func outputAudit(auditData validator.AuditData, outputFile, outputURL, outputFormat string, useColor bool, onlyShowFailedTests bool) {
+	if onlyShowFailedTests {
+		auditData = auditData.RemoveSuccessfulResults()
 	}
-	var auditData validator.AuditData
-	auditData, err = validator.RunAudit(c, k, onlyShowFailedTests)
-
-	if err != nil {
-		logrus.Errorf("Error while running audit on resources: %v", err)
-		os.Exit(1)
-	}
-
 	var outputBytes []byte
+	var err error
 	if outputFormat == "score" {
 		outputBytes = []byte(fmt.Sprintf("%d\n", auditData.GetSummary().GetScore()))
 	} else if outputFormat == "yaml" {
-		jsonBytes, err := json.Marshal(auditData)
+		var jsonBytes []byte
+		jsonBytes, err = json.Marshal(auditData)
 		if err == nil {
 			outputBytes, err = yaml.JSONToYAML(jsonBytes)
 		}
@@ -201,5 +203,4 @@ func runAndReportAudit(ctx context.Context, c conf.Configuration, auditPath, wor
 			}
 		}
 	}
-	return auditData
 }
diff --git a/pkg/dashboard/dashboard.go b/pkg/dashboard/dashboard.go
index cf86042b..17cb179d 100644
--- a/pkg/dashboard/dashboard.go
+++ b/pkg/dashboard/dashboard.go
@@ -181,7 +181,7 @@ func GetRouter(c config.Configuration, auditPath string, port int, basePath stri
 			}
 
 			var auditDataObj validator.AuditData
-			auditDataObj, err = validator.RunAudit(adjustedConf, k, false)
+			auditDataObj, err = validator.RunAudit(adjustedConf, k)
 			if err != nil {
 				http.Error(w, "Error Fetching Deployments", http.StatusInternalServerError)
 				return
@@ -214,7 +214,7 @@ func GetRouter(c config.Configuration, auditPath string, port int, basePath stri
 			}
 
 			var auditData validator.AuditData
-			auditData, err = validator.RunAudit(adjustedConf, k, false)
+			auditData, err = validator.RunAudit(adjustedConf, k)
 			if err != nil {
 				logrus.Errorf("Error getting audit data: %v", err)
 				http.Error(w, "Error running audit", 500)
diff --git a/pkg/validator/fullaudit.go b/pkg/validator/fullaudit.go
index e8a3b804..1bca5bb4 100644
--- a/pkg/validator/fullaudit.go
+++ b/pkg/validator/fullaudit.go
@@ -16,7 +16,7 @@ import (
 )
 
 // RunAudit runs a full Polaris audit and returns an AuditData object
-func RunAudit(config conf.Configuration, kubeResources *kube.ResourceProvider, onlyShowFailedTests bool) (AuditData, error) {
+func RunAudit(config conf.Configuration, kubeResources *kube.ResourceProvider) (AuditData, error) {
 	displayName := config.DisplayName
 	if displayName == "" {
 		displayName = kubeResources.SourceName
@@ -42,9 +42,6 @@ func RunAudit(config conf.Configuration, kubeResources *kube.ResourceProvider, o
 		Results: results,
 	}
 	auditData.Score = auditData.GetSummary().GetScore()
-	if onlyShowFailedTests {
-		auditData.RemoveSuccessfulResults()
-	}
 	return auditData, nil
 }
 
diff --git a/pkg/validator/output.go b/pkg/validator/output.go
index 5a99f0bd..cfb03e50 100644
--- a/pkg/validator/output.go
+++ b/pkg/validator/output.go
@@ -19,6 +19,7 @@ import (
 	"time"
 
 	"github.com/fatih/color"
+	"github.com/thoas/go-funk"
 
 	"github.com/fairwindsops/polaris/pkg/config"
 )
@@ -52,10 +53,12 @@ type AuditData struct {
 }
 
 // RemoveSuccessfulResults remove all test that have passed.
-func (res *AuditData) RemoveSuccessfulResults() {
-	for _, auditDataResult := range res.Results {
-		auditDataResult.removeSuccessfulResults()
-	}
+func (res AuditData) RemoveSuccessfulResults() AuditData {
+	resCopy := res
+	resCopy.Results = funk.Map(res.Results, func(auditDataResult Result) Result {
+		return auditDataResult.removeSuccessfulResults()
+	}).([]Result)
+	return resCopy
 }
 
 // ClusterInfo contains Polaris results as well as some high-level stats
@@ -80,12 +83,14 @@ type ResultMessage struct {
 // ResultSet contiains the results for a set of checks
 type ResultSet map[string]ResultMessage
 
-func (res ResultSet) removeSuccessfulResults() {
+func (res ResultSet) removeSuccessfulResults() ResultSet {
+	newResults := ResultSet{}
 	for k, resultMessage := range res {
-		if resultMessage.Success {
-			delete(res, k)
+		if !resultMessage.Success {
+			newResults[k] = resultMessage
 		}
 	}
+	return newResults
 }
 
 // Result provides results for a Kubernetes object
@@ -98,9 +103,14 @@ type Result struct {
 	CreatedTime time.Time
 }
 
-func (res *Result) removeSuccessfulResults() {
-	res.Results.removeSuccessfulResults()
-	res.PodResult.removeSuccessfulResults()
+func (res Result) removeSuccessfulResults() Result {
+	resCopy := res
+	resCopy.Results = res.Results.removeSuccessfulResults()
+	if res.PodResult != nil {
+		podCopy := res.PodResult.removeSuccessfulResults()
+		resCopy.PodResult = &podCopy
+	}
+	return resCopy
 }
 
 // PodResult provides a list of validation messages for each pod.
@@ -110,14 +120,13 @@ type PodResult struct {
 	ContainerResults []ContainerResult
 }
 
-func (res *PodResult) removeSuccessfulResults() {
-	if res == nil {
-		return
-	}
-	res.Results.removeSuccessfulResults()
-	for _, containerResult := range res.ContainerResults {
-		containerResult.removeSuccessfulResults()
-	}
+func (res PodResult) removeSuccessfulResults() PodResult {
+	resCopy := PodResult{}
+	resCopy.Results = res.Results.removeSuccessfulResults()
+	resCopy.ContainerResults = funk.Map(res.ContainerResults, func(containerResult ContainerResult) ContainerResult {
+		return containerResult.removeSuccessfulResults()
+	}).([]ContainerResult)
+	return resCopy
 }
 
 // ContainerResult provides a list of validation messages for each container.
@@ -126,8 +135,10 @@ type ContainerResult struct {
 	Results ResultSet
 }
 
-func (res *ContainerResult) removeSuccessfulResults() {
-	res.Results.removeSuccessfulResults()
+func (res ContainerResult) removeSuccessfulResults() ContainerResult {
+	resCopy := res
+	resCopy.Results = res.Results.removeSuccessfulResults()
+	return resCopy
 }
 
 func fillString(id string, l int) string {
diff --git a/pkg/validator/summary.go b/pkg/validator/summary.go
index ed455584..76c51912 100644
--- a/pkg/validator/summary.go
+++ b/pkg/validator/summary.go
@@ -23,7 +23,8 @@ func (cs CountSummary) GetScore() uint {
 	if total == 0 {
 		return uint(100)
 	}
-	return uint((float64(cs.Successes*2) / float64(total)) * 100)
+	score := uint((float64(cs.Successes*2) / float64(total)) * 100)
+	return score
 }
 
 // AddSummary adds two CountSummaries together


Test patch:
diff --git a/pkg/validator/fullaudit_test.go b/pkg/validator/fullaudit_test.go
index ad3e4164..eb6e7597 100644
--- a/pkg/validator/fullaudit_test.go
+++ b/pkg/validator/fullaudit_test.go
@@ -31,7 +31,7 @@ func TestGetTemplateData(t *testing.T) {
 	score := uint(0)
 
 	var actualAudit AuditData
-	actualAudit, err = RunAudit(c, resources, false)
+	actualAudit, err = RunAudit(c, resources)
 	assert.Equal(t, err, nil, "error should be nil")
 	assert.Equal(t, score, actualAudit.Score, "")
 	assert.EqualValues(t, sum, actualAudit.GetSummary())