Skip to content

Commit 1447e18

Browse files
feat: Allow templating of outcome messages for the JSON/YAML compare analyzers (#1432)
* feat: allow templating of the outcome message for the JSON and YAML Compare analyzers * Update pkg/analyze/json_compare.go Co-authored-by: Evans Mungai <[email protected]>
1 parent 37a5cce commit 1447e18

File tree

7 files changed

+196
-4
lines changed

7 files changed

+196
-4
lines changed

Makefile

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,8 @@ CONTROLLER_GEN=$(shell which controller-gen)
165165

166166
.PHONY: client-gen
167167
client-gen:
168-
ifeq (, $(shell which client-gen 2>/dev/null))
169168
go install k8s.io/code-generator/cmd/[email protected]
170169
CLIENT_GEN=$(shell go env GOPATH)/bin/client-gen
171-
else
172-
CLIENT_GEN=$(shell which client-gen)
173-
endif
174170

175171
.PHONY: release
176172
release: export GITHUB_TOKEN = $(shell echo ${GITHUB_TOKEN_TROUBLESHOOT})

internal/util/util.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package util
22

33
import (
4+
"bytes"
45
"net/url"
56
"os"
67
"strings"
8+
"text/template"
79

810
"golang.org/x/text/cases"
911
"golang.org/x/text/language"
@@ -82,3 +84,24 @@ func IsInCluster() bool {
8284

8385
return true
8486
}
87+
88+
// RenderTemplate renders a template and returns the result as a string
89+
func RenderTemplate(tpl string, data interface{}) (string, error) {
90+
// Create a new template and parse the letter into it
91+
t, err := template.New("data").Parse(tpl)
92+
if err != nil {
93+
return "", err
94+
}
95+
96+
// Create a new buffer
97+
buf := new(bytes.Buffer)
98+
99+
// Execute the template and write the bytes to the buffer
100+
err = t.Execute(buf, data)
101+
if err != nil {
102+
return "", err
103+
}
104+
105+
// Return the string representation of the buffer
106+
return buf.String(), nil
107+
}

internal/util/util_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,59 @@ func TestAppend(t *testing.T) {
246246
})
247247
}
248248
}
249+
250+
func TestRenderTemplate(t *testing.T) {
251+
tests := []struct {
252+
name string
253+
tpl string
254+
data interface{}
255+
want string
256+
wantErr bool
257+
}{
258+
{
259+
name: "empty template and data",
260+
tpl: "",
261+
data: nil,
262+
want: "",
263+
wantErr: false,
264+
},
265+
{
266+
name: "empty template with data",
267+
tpl: "",
268+
data: map[string]string{"Name": "World"},
269+
want: "",
270+
wantErr: false,
271+
},
272+
{
273+
name: "empty data with template with no keys",
274+
tpl: "Hello, World!",
275+
data: nil,
276+
want: "Hello, World!",
277+
wantErr: false,
278+
},
279+
{
280+
name: "simple template",
281+
tpl: "Hello, {{ .Name }}!",
282+
data: map[string]string{"Name": "World"},
283+
want: "Hello, World!",
284+
wantErr: false,
285+
},
286+
{
287+
name: "template with missing key",
288+
tpl: "Hello, {{ .Name }}!",
289+
data: map[string]string{"Name2": "World"},
290+
want: "Hello, <no value>!",
291+
wantErr: false,
292+
},
293+
}
294+
for _, tt := range tests {
295+
t.Run(tt.name, func(t *testing.T) {
296+
got, err := RenderTemplate(tt.tpl, tt.data)
297+
if (err != nil) != tt.wantErr {
298+
t.Errorf("RenderTemplate() error = %v, wantErr %v", err, tt.wantErr)
299+
return
300+
}
301+
assert.Equal(t, tt.want, got, "RenderTemplate() = %v, want %v", got, tt.want)
302+
})
303+
}
304+
}

pkg/analyze/json_compare.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strconv"
1111

1212
"github.com/pkg/errors"
13+
util "github.com/replicatedhq/troubleshoot/internal/util"
1314
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
1415
iutils "github.com/replicatedhq/troubleshoot/pkg/interfaceutils"
1516
"k8s.io/client-go/util/jsonpath"
@@ -54,6 +55,8 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
5455
return nil, errors.Wrap(err, "failed to parse collected data as json")
5556
}
5657

58+
originalActual := actual
59+
5760
if analyzer.Path != "" {
5861
actual, err = iutils.GetAtPath(actual, analyzer.Path)
5962
if err != nil {
@@ -112,6 +115,11 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
112115
}
113116
}
114117

118+
outcome.Fail.Message, err = util.RenderTemplate(outcome.Fail.Message, originalActual)
119+
if err != nil {
120+
return nil, errors.Wrap(err, "failed to render template on outcome message")
121+
}
122+
115123
if when == equal {
116124
result.IsFail = true
117125
result.Message = outcome.Fail.Message
@@ -128,6 +136,11 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
128136
}
129137
}
130138

139+
outcome.Warn.Message, err = util.RenderTemplate(outcome.Warn.Message, originalActual)
140+
if err != nil {
141+
return nil, errors.Wrap(err, "failed to render template on outcome message")
142+
}
143+
131144
if when == equal {
132145
result.IsWarn = true
133146
result.Message = outcome.Warn.Message
@@ -144,6 +157,11 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
144157
}
145158
}
146159

160+
outcome.Pass.Message, err = util.RenderTemplate(outcome.Pass.Message, originalActual)
161+
if err != nil {
162+
return nil, errors.Wrap(err, "failed to render template on outcome message")
163+
}
164+
147165
if when == equal {
148166
result.IsPass = true
149167
result.Message = outcome.Pass.Message

pkg/analyze/json_compare_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,48 @@ func Test_jsonCompare(t *testing.T) {
756756
]
757757
}`),
758758
},
759+
{
760+
name: "basic comparison with outcome message templated",
761+
analyzer: troubleshootv1beta2.JsonCompare{
762+
Outcomes: []*troubleshootv1beta2.Outcome{
763+
{
764+
Pass: &troubleshootv1beta2.SingleOutcome{
765+
Message: "Status: {{ .morestuff.status }}, Info: {{ .morestuff.info }}",
766+
When: "true",
767+
},
768+
},
769+
{
770+
Fail: &troubleshootv1beta2.SingleOutcome{
771+
Message: "Status: {{ .morestuff.status }}, Info: {{ .morestuff.info }}",
772+
When: "false",
773+
},
774+
},
775+
},
776+
CollectorName: "json-compare",
777+
FileName: "json-compare.json",
778+
Path: "morestuff.status",
779+
Value: `"ready"`,
780+
},
781+
expectResult: AnalyzeResult{
782+
IsPass: false,
783+
IsWarn: false,
784+
IsFail: true,
785+
Title: "json-compare",
786+
Message: "Status: notready, Info: morestuff is not ready",
787+
IconKey: "kubernetes_text_analyze",
788+
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
789+
},
790+
fileContents: []byte(`{
791+
"stuff": {
792+
"status": "ready",
793+
"info": "this stuff is ready"
794+
},
795+
"morestuff": {
796+
"status": "notready",
797+
"info": "morestuff is not ready"
798+
}
799+
}`),
800+
},
759801
}
760802

761803
for _, test := range tests {

pkg/analyze/yaml_compare.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strconv"
77

88
"github.com/pkg/errors"
9+
util "github.com/replicatedhq/troubleshoot/internal/util"
910
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
1011
iutils "github.com/replicatedhq/troubleshoot/pkg/interfaceutils"
1112
"gopkg.in/yaml.v2"
@@ -50,6 +51,8 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
5051
return nil, errors.Wrap(err, "failed to parse collected data as yaml doc")
5152
}
5253

54+
originalActual := actual
55+
5356
if analyzer.Path != "" {
5457
actual, err = iutils.GetAtPath(actual, analyzer.Path)
5558
if err != nil {
@@ -81,6 +84,11 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
8184
}
8285
}
8386

87+
outcome.Fail.Message, err = util.RenderTemplate(outcome.Fail.Message, originalActual)
88+
if err != nil {
89+
return nil, errors.Wrap(err, "failed to render template on outcome message")
90+
}
91+
8492
if when == equal {
8593
result.IsFail = true
8694
result.Message = outcome.Fail.Message
@@ -96,6 +104,11 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
96104
}
97105
}
98106

107+
outcome.Warn.Message, err = util.RenderTemplate(outcome.Warn.Message, originalActual)
108+
if err != nil {
109+
return nil, errors.Wrap(err, "failed to render template on outcome message")
110+
}
111+
99112
if when == equal {
100113
result.IsWarn = true
101114
result.Message = outcome.Warn.Message
@@ -111,6 +124,11 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
111124
}
112125
}
113126

127+
outcome.Pass.Message, err = util.RenderTemplate(outcome.Pass.Message, originalActual)
128+
if err != nil {
129+
return nil, errors.Wrap(err, "failed to render template on outcome message")
130+
}
131+
114132
if when == equal {
115133
result.IsPass = true
116134
result.Message = outcome.Pass.Message

pkg/analyze/yaml_compare_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,45 @@ otherstuff:
430430
},
431431
fileContents: []byte(``),
432432
},
433+
{
434+
name: "basic comparison with outcome message templated",
435+
analyzer: troubleshootv1beta2.YamlCompare{
436+
Outcomes: []*troubleshootv1beta2.Outcome{
437+
{
438+
Pass: &troubleshootv1beta2.SingleOutcome{
439+
Message: "Status: {{ .stuff.status }}, Info: {{ .stuff.info }}",
440+
When: "true",
441+
},
442+
},
443+
{
444+
Fail: &troubleshootv1beta2.SingleOutcome{
445+
Message: "Status: {{ .stuff.status }}, Info: {{ .stuff.info }}",
446+
When: "false",
447+
},
448+
},
449+
},
450+
CollectorName: "yaml-compare",
451+
FileName: "yaml-compare.yaml",
452+
Value: `ready`,
453+
Path: "stuff.status",
454+
},
455+
expectResult: AnalyzeResult{
456+
IsPass: true,
457+
IsWarn: false,
458+
IsFail: false,
459+
Title: "yaml-compare",
460+
Message: "Status: ready, Info: stuff is ready",
461+
IconKey: "kubernetes_text_analyze",
462+
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
463+
},
464+
fileContents: []byte(`
465+
stuff:
466+
status: ready
467+
info: stuff is ready
468+
morestuff:
469+
status: notready
470+
info: morestuff is not ready`),
471+
},
433472
}
434473

435474
for _, test := range tests {

0 commit comments

Comments
 (0)