Skip to content

Commit 06da4d7

Browse files
Clean up formatting
1 parent 0ecbc1d commit 06da4d7

File tree

5 files changed

+196
-66
lines changed

5 files changed

+196
-66
lines changed

cmd/kubeapply/subcmd/validate.go

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package subcmd
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"path/filepath"
78

@@ -144,69 +145,27 @@ func execValidation(ctx context.Context, clusterConfig *config.ClusterConfig) er
144145
return err
145146
}
146147

147-
numInvalidResourceChecks := 0
148-
numValidResourceChecks := 0
149-
numSkippedResourceChecks := 0
150-
151-
for _, result := range results {
152-
for _, checkResult := range result.CheckResults {
153-
switch checkResult.Status {
154-
case validation.StatusValid:
155-
numValidResourceChecks++
156-
log.Debugf(
157-
"Resource %s in file %s OK according to check %s",
158-
result.Resource.PrettyName(),
159-
result.Resource.Path,
160-
checkResult.CheckName,
161-
)
162-
case validation.StatusSkipped:
163-
numSkippedResourceChecks++
164-
log.Debugf(
165-
"Resource %s in file %s was skipped by check %s",
166-
result.Resource.PrettyName(),
167-
result.Resource.Path,
168-
checkResult.CheckName,
169-
)
170-
case validation.StatusError:
171-
numInvalidResourceChecks++
172-
log.Errorf(
173-
"Resource %s in file %s could not be processed by check %s: %s",
174-
result.Resource.PrettyName(),
175-
result.Resource.Path,
176-
checkResult.CheckName,
177-
checkResult.Message,
178-
)
179-
case validation.StatusInvalid:
180-
numInvalidResourceChecks++
181-
log.Errorf(
182-
"Resource %s in file %s is invalid according to check %s: %s",
183-
result.Resource.PrettyName(),
184-
result.Resource.Path,
185-
checkResult.CheckName,
186-
checkResult.Message,
187-
)
188-
case validation.StatusEmpty:
189-
default:
190-
log.Infof("Unrecognized result type: %+v", result)
191-
}
148+
counts := validation.CountsByStatus(results)
149+
resultsWithIssues := validation.ResultsWithIssues(results)
150+
151+
if len(resultsWithIssues) > 0 {
152+
log.Warnf("Found %d resources with potential issues", len(resultsWithIssues))
153+
for _, result := range resultsWithIssues {
154+
fmt.Println(
155+
validation.ResultTable(
156+
result,
157+
clusterConfig.DescriptiveName(),
158+
clusterConfig.ExpandedPath,
159+
debug,
160+
),
161+
)
192162
}
193163
}
194164

195-
if numInvalidResourceChecks > 0 {
196-
return fmt.Errorf(
197-
"Validation failed for %d resources in cluster %s (%d checks valid, %d skipped)",
198-
numInvalidResourceChecks,
199-
clusterConfig.DescriptiveName(),
200-
numValidResourceChecks,
201-
numSkippedResourceChecks,
202-
)
165+
if counts[validation.StatusError]+counts[validation.StatusInvalid] > 0 {
166+
return errors.New("Validation failed")
203167
}
204168

205-
log.Infof(
206-
"Validation of cluster %s passed (%d checks valid, %d skipped)",
207-
clusterConfig.DescriptiveName(),
208-
numValidResourceChecks,
209-
numSkippedResourceChecks,
210-
)
169+
log.Infof("Validation passed")
211170
return nil
212171
}

pkg/validation/format.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package validation
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"path/filepath"
7+
"strings"
8+
9+
"github.com/fatih/color"
10+
"github.com/olekukonko/tablewriter"
11+
)
12+
13+
func ResultTable(
14+
result ResourceResult,
15+
clusterName string,
16+
baseDir string,
17+
verbose bool,
18+
) string {
19+
buf := &bytes.Buffer{}
20+
21+
table := tablewriter.NewWriter(buf)
22+
table.SetHeader(
23+
[]string{
24+
"Property",
25+
"Value",
26+
},
27+
)
28+
table.SetAutoWrapText(false)
29+
table.SetColumnAlignment(
30+
[]int{
31+
tablewriter.ALIGN_RIGHT,
32+
tablewriter.ALIGN_LEFT,
33+
},
34+
)
35+
table.SetBorders(
36+
tablewriter.Border{
37+
Left: false,
38+
Top: true,
39+
Right: false,
40+
Bottom: true,
41+
},
42+
)
43+
44+
if clusterName != "" {
45+
table.Append(
46+
[]string{
47+
"cluster",
48+
clusterName,
49+
},
50+
)
51+
}
52+
53+
var displayPath string
54+
55+
relPath, err := filepath.Rel(baseDir, result.Resource.Path)
56+
if err != nil {
57+
displayPath = result.Resource.Path
58+
} else {
59+
displayPath = relPath
60+
}
61+
62+
table.Append(
63+
[]string{
64+
"path",
65+
displayPath,
66+
},
67+
)
68+
table.Append(
69+
[]string{
70+
"resource",
71+
result.Resource.PrettyName(),
72+
},
73+
)
74+
75+
errorPrinter := color.New(color.FgHiRed).SprintfFunc()
76+
warnPrinter := color.New(color.FgHiYellow).SprintfFunc()
77+
standardPrinter := fmt.Sprintf
78+
79+
for _, checkResult := range result.CheckResults {
80+
if !verbose && (checkResult.Status != StatusError &&
81+
checkResult.Status != StatusInvalid &&
82+
checkResult.Status != StatusWarning) {
83+
continue
84+
}
85+
86+
reasonLines := []string{checkResult.Message}
87+
for r, reason := range checkResult.Reasons {
88+
reasonLines = append(reasonLines, fmt.Sprintf("(%d) %s", r+1, reason))
89+
}
90+
91+
table.Append(
92+
[]string{
93+
"checkType",
94+
string(checkResult.CheckType),
95+
},
96+
)
97+
table.Append(
98+
[]string{
99+
"checkName",
100+
checkResult.CheckName,
101+
},
102+
)
103+
104+
var printer func(f string, a ...interface{}) string
105+
switch checkResult.Status {
106+
case StatusError, StatusInvalid:
107+
printer = errorPrinter
108+
case StatusWarning:
109+
printer = warnPrinter
110+
default:
111+
printer = standardPrinter
112+
}
113+
114+
table.Append(
115+
[]string{
116+
"checkStatus",
117+
printer(string(checkResult.Status)),
118+
},
119+
)
120+
121+
table.Append(
122+
[]string{
123+
"checkMessage",
124+
strings.Join(reasonLines, "\n"),
125+
},
126+
)
127+
}
128+
129+
table.Render()
130+
return string(bytes.TrimRight(buf.Bytes(), "\n"))
131+
}

pkg/validation/result.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const (
2121
)
2222

2323
// Result stores the results of validating a single resource in a single file, for all checks.
24-
type Result struct {
24+
type ResourceResult struct {
2525
Resource Resource
2626
CheckResults []CheckResult
2727
}
@@ -34,3 +34,43 @@ type CheckResult struct {
3434
Message string
3535
Reasons []string
3636
}
37+
38+
// HasIssues returns whether a ResourceResult has at least one check result with an
39+
// error or warning.
40+
func (r ResourceResult) HasIssues() bool {
41+
for _, checkResult := range r.CheckResults {
42+
if checkResult.Status == StatusError || checkResult.Status == StatusInvalid ||
43+
checkResult.Status == StatusWarning {
44+
return true
45+
}
46+
}
47+
48+
return false
49+
}
50+
51+
// CountsByStatus returns the number of check results for each status type.
52+
func CountsByStatus(results []ResourceResult) map[Status]int {
53+
counts := map[Status]int{}
54+
55+
for _, result := range results {
56+
for _, checkResult := range result.CheckResults {
57+
counts[checkResult.Status]++
58+
}
59+
}
60+
61+
return counts
62+
}
63+
64+
// ResultsWithIssues filters the argument resource results to just those with potential
65+
// issues.
66+
func ResultsWithIssues(results []ResourceResult) []ResourceResult {
67+
filteredResults := []ResourceResult{}
68+
69+
for _, result := range results {
70+
if result.HasIssues() {
71+
filteredResults = append(filteredResults, result)
72+
}
73+
}
74+
75+
return filteredResults
76+
}

pkg/validation/validation.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func NewKubeValidator(config KubeValidatorConfig) *KubeValidator {
3737
func (k *KubeValidator) RunChecks(
3838
ctx context.Context,
3939
path string,
40-
) ([]Result, error) {
40+
) ([]ResourceResult, error) {
4141
resources := []Resource{}
4242
index := 0
4343

@@ -87,12 +87,12 @@ func (k *KubeValidator) RunChecks(
8787
}
8888
defer close(resourcesChan)
8989

90-
resultsChan := make(chan Result, len(resources))
90+
resultsChan := make(chan ResourceResult, len(resources))
9191

9292
for i := 0; i < k.config.NumWorkers; i++ {
9393
go func() {
9494
for resource := range resourcesChan {
95-
result := Result{
95+
result := ResourceResult{
9696
Resource: resource,
9797
}
9898
for _, checker := range k.config.Checkers {
@@ -107,7 +107,7 @@ func (k *KubeValidator) RunChecks(
107107
}()
108108
}
109109

110-
results := []Result{}
110+
results := []ResourceResult{}
111111
for i := 0; i < len(resources); i++ {
112112
results = append(results, <-resultsChan)
113113
}

pkg/validation/validation_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ func TestKubeValidator(t *testing.T) {
2323

2424
type testCase struct {
2525
path string
26-
expected []Result
26+
expected []ResourceResult
2727
}
2828

2929
testCases := []testCase{
3030
{
3131
path: "testdata/configs",
32-
expected: []Result{
32+
expected: []ResourceResult{
3333
{
3434
Resource: Resource{
3535
Path: "testdata/configs/deployment.yaml",

0 commit comments

Comments
 (0)