Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit 66d3837

Browse files
author
priyawadhwa
authored
Merge pull request #173 from priyawadhwa/cleanup-output
Add --format flag to customize output
2 parents f92bed7 + 1cf9c86 commit 66d3837

File tree

5 files changed

+77
-19
lines changed

5 files changed

+77
-19
lines changed

README.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,42 @@ type MultiVersionInfo struct {
239239
}
240240
```
241241

242+
## User Customized Output
243+
Users can customize the format of the output of diffs with the`--format` flag. The flag takes a Go template string, which specifies the format the diff should be output in. This template string uses the structs described above, depending on the differ used, to format output. The default template strings container-diff uses can be found [here](https://github.com/GoogleCloudPlatform/container-diff/blob/master/util/template_utils.go).
244+
245+
An example using the pip package analyzer is shown below, in which only package names are printed (some are repeated because of version differences).
246+
247+
```shell
248+
$ container-diff analyze gcr.io/google-appengine/python:latest --type=pip --format='
249+
-----{{.AnalyzeType}}-----
250+
Packages found in {{.Image}}:{{if not .Analysis}} None{{else}}
251+
{{range .Analysis}}{{"\n"}}{{.Name}}{{end}}
252+
{{end}}
253+
'
254+
Retrieving image gcr.io/google-appengine/python:latest from source Cloud Registry
255+
Retrieving analyses
256+
257+
-----Pip-----
258+
Packages found in gcr.io/google-appengine/python:latest:
259+
260+
chardet
261+
colorama
262+
html5lib
263+
mercurial
264+
pip
265+
pip
266+
pip
267+
requests
268+
setuptools
269+
setuptools
270+
setuptools
271+
six
272+
urllib3
273+
virtualenv
274+
wheel
275+
wheel
276+
```
277+
242278
## Known issues
243279

244280
To run container-diff using image IDs, docker must be installed.
@@ -422,7 +458,7 @@ If using existing package tools, you should create the appropriate structs (e.g.
422458
```go
423459
type Result interface {
424460
OutputStruct() interface{}
425-
OutputText(resultType string) error
461+
OutputText(resultType string, format string) error
426462
}
427463
```
428464

cmd/root.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ var types diffTypes
4141
var noCache bool
4242

4343
var LogLevel string
44+
var format string
4445

4546
type validatefxn func(args []string) error
4647

@@ -84,7 +85,7 @@ func outputResults(resultMap map[string]util.Result) {
8485
if json {
8586
results[i] = result.OutputStruct()
8687
} else {
87-
err := result.OutputText(analyzerType)
88+
err := result.OutputText(analyzerType, format)
8889
if err != nil {
8990
logrus.Error(err)
9091
}
@@ -178,6 +179,7 @@ func cacheDir() (string, error) {
178179

179180
func init() {
180181
RootCmd.PersistentFlags().StringVarP(&LogLevel, "verbosity", "v", "warning", "This flag controls the verbosity of container-diff.")
182+
RootCmd.PersistentFlags().StringVarP(&format, "format", "", "", "Format to output diff in.")
181183
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
182184
}
183185

util/analyze_output_utils.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626

2727
type Result interface {
2828
OutputStruct() interface{}
29-
OutputText(resultType string) error
29+
OutputText(resultType string, format string) error
3030
}
3131

3232
type AnalyzeResult struct {
@@ -41,15 +41,15 @@ func (r ListAnalyzeResult) OutputStruct() interface{} {
4141
return r
4242
}
4343

44-
func (r ListAnalyzeResult) OutputText(resultType string) error {
44+
func (r ListAnalyzeResult) OutputText(resultType string, format string) error {
4545
analysis, valid := r.Analysis.([]string)
4646
if !valid {
4747
logrus.Error("Unexpected structure of Analysis. Should be of type []string")
4848
return fmt.Errorf("Could not output %s analysis result", r.AnalyzeType)
4949
}
5050
r.Analysis = analysis
51+
return TemplateOutputFromFormat(r, "ListAnalyze", format)
5152

52-
return TemplateOutput(r, "ListAnalyze")
5353
}
5454

5555
type MultiVersionPackageAnalyzeResult AnalyzeResult
@@ -73,7 +73,7 @@ func (r MultiVersionPackageAnalyzeResult) OutputStruct() interface{} {
7373
return output
7474
}
7575

76-
func (r MultiVersionPackageAnalyzeResult) OutputText(resultType string) error {
76+
func (r MultiVersionPackageAnalyzeResult) OutputText(resultType string, format string) error {
7777
analysis, valid := r.Analysis.(map[string]map[string]PackageInfo)
7878
if !valid {
7979
logrus.Error("Unexpected structure of Analysis. Should be of type map[string]map[string]PackageInfo")
@@ -91,7 +91,7 @@ func (r MultiVersionPackageAnalyzeResult) OutputText(resultType string) error {
9191
AnalyzeType: r.AnalyzeType,
9292
Analysis: strAnalysis,
9393
}
94-
return TemplateOutput(strResult, "MultiVersionPackageAnalyze")
94+
return TemplateOutputFromFormat(strResult, "MultiVersionPackageAnalyze", format)
9595
}
9696

9797
type SingleVersionPackageAnalyzeResult AnalyzeResult
@@ -115,7 +115,7 @@ func (r SingleVersionPackageAnalyzeResult) OutputStruct() interface{} {
115115
return output
116116
}
117117

118-
func (r SingleVersionPackageAnalyzeResult) OutputText(diffType string) error {
118+
func (r SingleVersionPackageAnalyzeResult) OutputText(diffType string, format string) error {
119119
analysis, valid := r.Analysis.(map[string]PackageInfo)
120120
if !valid {
121121
logrus.Error("Unexpected structure of Analysis. Should be of type map[string]PackageInfo")
@@ -133,7 +133,7 @@ func (r SingleVersionPackageAnalyzeResult) OutputText(diffType string) error {
133133
AnalyzeType: r.AnalyzeType,
134134
Analysis: strAnalysis,
135135
}
136-
return TemplateOutput(strResult, "SingleVersionPackageAnalyze")
136+
return TemplateOutputFromFormat(strResult, "SingleVersionPackageAnalyze", format)
137137
}
138138

139139
type PackageOutput struct {
@@ -191,7 +191,7 @@ func (r FileAnalyzeResult) OutputStruct() interface{} {
191191
return r
192192
}
193193

194-
func (r FileAnalyzeResult) OutputText(analyzeType string) error {
194+
func (r FileAnalyzeResult) OutputText(analyzeType string, format string) error {
195195
analysis, valid := r.Analysis.([]util.DirectoryEntry)
196196
if !valid {
197197
logrus.Error("Unexpected structure of Analysis. Should be of type []DirectoryEntry")
@@ -214,5 +214,5 @@ func (r FileAnalyzeResult) OutputText(analyzeType string) error {
214214
AnalyzeType: r.AnalyzeType,
215215
Analysis: strAnalysis,
216216
}
217-
return TemplateOutput(strResult, "FileAnalyze")
217+
return TemplateOutputFromFormat(strResult, "FileAnalyze", format)
218218
}

util/diff_output_utils.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (r MultiVersionPackageDiffResult) OutputStruct() interface{} {
5252
return r
5353
}
5454

55-
func (r MultiVersionPackageDiffResult) OutputText(diffType string) error {
55+
func (r MultiVersionPackageDiffResult) OutputText(diffType string, format string) error {
5656
diff, valid := r.Diff.(MultiVersionPackageDiff)
5757
if !valid {
5858
logrus.Error("Unexpected structure of Diff. Should follow the MultiVersionPackageDiff struct")
@@ -84,7 +84,7 @@ func (r MultiVersionPackageDiffResult) OutputText(diffType string) error {
8484
InfoDiff: strInfoDiff,
8585
},
8686
}
87-
return TemplateOutput(strResult, "MultiVersionPackageDiff")
87+
return TemplateOutputFromFormat(strResult, "MultiVersionPackageDiff", format)
8888
}
8989

9090
func getMultiVersionInfoDiffOutput(infoDiff []MultiVersionInfo) []MultiVersionInfo {
@@ -118,7 +118,7 @@ func (r SingleVersionPackageDiffResult) OutputStruct() interface{} {
118118
return r
119119
}
120120

121-
func (r SingleVersionPackageDiffResult) OutputText(diffType string) error {
121+
func (r SingleVersionPackageDiffResult) OutputText(diffType string, format string) error {
122122
diff, valid := r.Diff.(PackageDiff)
123123
if !valid {
124124
logrus.Error("Unexpected structure of Diff. Should follow the PackageDiff struct")
@@ -150,7 +150,7 @@ func (r SingleVersionPackageDiffResult) OutputText(diffType string) error {
150150
InfoDiff: strInfoDiff,
151151
},
152152
}
153-
return TemplateOutput(strResult, "SingleVersionPackageDiff")
153+
return TemplateOutputFromFormat(strResult, "SingleVersionPackageDiff", format)
154154
}
155155

156156
func getSingleVersionInfoDiffOutput(infoDiff []Info) []Info {
@@ -168,8 +168,8 @@ func (r HistDiffResult) OutputStruct() interface{} {
168168
return r
169169
}
170170

171-
func (r HistDiffResult) OutputText(diffType string) error {
172-
return TemplateOutput(r, "HistDiff")
171+
func (r HistDiffResult) OutputText(diffType string, format string) error {
172+
return TemplateOutputFromFormat(r, "HistDiff", format)
173173
}
174174

175175
type DirDiffResult DiffResult
@@ -185,7 +185,7 @@ func (r DirDiffResult) OutputStruct() interface{} {
185185
return r
186186
}
187187

188-
func (r DirDiffResult) OutputText(diffType string) error {
188+
func (r DirDiffResult) OutputText(diffType string, format string) error {
189189
diff, valid := r.Diff.(DirDiff)
190190
if !valid {
191191
logrus.Error("Unexpected structure of Diff. Should follow the DirDiff struct")
@@ -218,5 +218,5 @@ func (r DirDiffResult) OutputText(diffType string) error {
218218
Mods: strMods,
219219
},
220220
}
221-
return TemplateOutput(strResult, "DirDiff")
221+
return TemplateOutputFromFormat(strResult, "DirDiff", format)
222222
}

util/format_utils.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,23 @@ func TemplateOutput(diff interface{}, templateType string) error {
7979
w.Flush()
8080
return nil
8181
}
82+
83+
func TemplateOutputFromFormat(diff interface{}, templateType string, format string) error {
84+
if format == "" {
85+
return TemplateOutput(diff, templateType)
86+
}
87+
funcs := template.FuncMap{"join": strings.Join}
88+
tmpl, err := template.New("tmpl").Funcs(funcs).Parse(format)
89+
if err != nil {
90+
logrus.Warningf("User specified format resulted in error, printing default output.")
91+
logrus.Error(err)
92+
return TemplateOutput(diff, templateType)
93+
}
94+
w := tabwriter.NewWriter(os.Stdout, 8, 8, 8, ' ', 0)
95+
err = tmpl.Execute(w, diff)
96+
if err != nil {
97+
return err
98+
}
99+
w.Flush()
100+
return nil
101+
}

0 commit comments

Comments
 (0)