Skip to content

Commit 9de26fd

Browse files
rickygodoymikouaj
authored andcommitted
Adding -json flag to output results to stdout in JSON format (#147)
* Adding -json flag to output results to stdout in JSON format * Updating user guide README * Fixing userguide MD format * Removig trailing space
1 parent 45289d2 commit 9de26fd

File tree

7 files changed

+134
-0
lines changed

7 files changed

+134
-0
lines changed

docs/user-guide.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,19 @@ policyExclusions:
287287
The GKE Policy Automation tool produces cluster validation results to the stderr, local JSON file,
288288
file on a GCS bucket and Pub/Sub topic.
289289

290+
### Console JSON output
291+
292+
The validation results can be displayed in the console standard output in a JSON format using the
293+
```-json``` flag.
294+
295+
Example of enabling JSON standard output in a command line:
296+
297+
```sh
298+
./gke-policy check \
299+
--project my-project --location europe-west2 --name my-cluster \
300+
-json
301+
```
302+
290303
### Local JSON file
291304

292305
The validation results can be stored in the local file in a JSON format.

internal/app/app.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ func (p *PolicyAutomationApp) LoadConfig(config *cfg.Config) (err error) {
119119
if !p.config.SilentMode {
120120
p.out = outputs.NewStdOutOutput()
121121
p.collectors = []outputs.ValidationResultCollector{outputs.NewConsoleResultCollector(p.out)}
122+
123+
if p.config.JsonOutput {
124+
p.out = outputs.NewSilentOutput()
125+
p.collectors = []outputs.ValidationResultCollector{outputs.NewConsoleJsonResultCollector(outputs.NewStdOutOutput())}
126+
}
127+
122128
p.clusterDumpCollectors = append(p.clusterDumpCollectors, outputs.NewOutputClusterDumpCollector(p.out))
123129
}
124130
if p.config.DumpFile != "" {
@@ -351,6 +357,7 @@ func newConfigFromFile(path string) (*cfg.Config, error) {
351357
func newConfigFromCli(cliConfig *CliConfig) *cfg.Config {
352358
config := &cfg.Config{}
353359
config.SilentMode = cliConfig.SilentMode
360+
config.JsonOutput = cliConfig.JsonOutput
354361
config.K8SApiConfig.Enabled = cliConfig.K8SCheck
355362
config.CredentialsFile = cliConfig.CredentialsFile
356363
config.DumpFile = cliConfig.DumpFile

internal/app/app_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ func TestLoadConfig(t *testing.T) {
165165
func TestNewConfigFromCli(t *testing.T) {
166166
input := &CliConfig{
167167
SilentMode: true,
168+
JsonOutput: true,
168169
CredentialsFile: "/path/to/creds.json",
169170
ClusterName: "testCluster",
170171
ClusterLocation: "europe-central2",
@@ -177,6 +178,9 @@ func TestNewConfigFromCli(t *testing.T) {
177178
if config.SilentMode != input.SilentMode {
178179
t.Errorf("silentMode = %v; want %v", config.SilentMode, input.SilentMode)
179180
}
181+
if config.JsonOutput != input.JsonOutput {
182+
t.Errorf("jsonOutput = %v; want %v", config.JsonOutput, input.JsonOutput)
183+
}
180184
if config.CredentialsFile != input.CredentialsFile {
181185
t.Errorf("credentialsFile = %v; want %v", config.CredentialsFile, input.CredentialsFile)
182186
}

internal/app/cli.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
type CliConfig struct {
2323
ConfigFile string
2424
SilentMode bool
25+
JsonOutput bool
2526
K8SCheck bool
2627
CredentialsFile string
2728
DumpFile string
@@ -267,6 +268,11 @@ func getOutputFlags(config *CliConfig) []cli.Flag {
267268
Usage: "Path to the file for storing results",
268269
Destination: &config.OutputFile,
269270
},
271+
&cli.BoolFlag{
272+
Name: "json",
273+
Usage: "Outputs results to standard console in JSON format",
274+
Destination: &config.JsonOutput,
275+
},
270276
}
271277
}
272278

internal/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type ValidateConfig func(config Config) error
3939

4040
type Config struct {
4141
SilentMode bool `yaml:"silent"`
42+
JsonOutput bool `yaml:"jsonOutput"`
4243
DumpFile string `yaml:"dumpFile"`
4344
CredentialsFile string `yaml:"credentialsFile"`
4445
Clusters []ConfigCluster `yaml:"clusters"`
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package outputs
16+
17+
import (
18+
"github.com/google/gke-policy-automation/internal/policy"
19+
)
20+
21+
type consoleJsonResultCollector struct {
22+
out *Output
23+
reportMapper ValidationReportMapper
24+
}
25+
26+
func NewConsoleJsonResultCollector(output *Output) ValidationResultCollector {
27+
return &consoleJsonResultCollector{
28+
out: output,
29+
reportMapper: NewValidationReportMapper(),
30+
}
31+
}
32+
33+
func (p *consoleJsonResultCollector) RegisterResult(results []*policy.PolicyEvaluationResult) error {
34+
p.reportMapper.AddResults(results)
35+
return nil
36+
}
37+
38+
func (p *consoleJsonResultCollector) Close() error {
39+
40+
jsonResult, err := p.reportMapper.GetJsonReport()
41+
42+
if err != nil {
43+
return err
44+
}
45+
46+
p.out.Printf(string(jsonResult))
47+
return nil
48+
}
49+
50+
func (p *consoleJsonResultCollector) Name() string {
51+
return "console json"
52+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package outputs
16+
17+
import (
18+
"bytes"
19+
"testing"
20+
21+
"github.com/google/gke-policy-automation/internal/policy"
22+
)
23+
24+
func TestConsoleJsonResultCollector(t *testing.T) {
25+
var buff bytes.Buffer
26+
var expectedJson = "json string"
27+
28+
out := &Output{w: &buff}
29+
reportMapperMock := &validationReportMapperMock{
30+
addResultsFn: func(results []*policy.PolicyEvaluationResult) {},
31+
getJsonReportFn: func() ([]byte, error) {
32+
return []byte(expectedJson), nil
33+
},
34+
}
35+
36+
collector := &consoleJsonResultCollector{out: out, reportMapper: reportMapperMock}
37+
err := collector.RegisterResult([]*policy.PolicyEvaluationResult{{}})
38+
if err != nil {
39+
t.Fatalf("err on RegisterResult = %v; want nil", err)
40+
}
41+
err = collector.Close()
42+
if err != nil {
43+
t.Fatalf("err on Close = %v; want nil", err)
44+
}
45+
if len(buff.String()) <= 0 {
46+
t.Errorf("nothing was written to the output buffer")
47+
}
48+
if buff.String() != expectedJson {
49+
t.Errorf("expected \"%v\" but buffer was \"%v\"", expectedJson, buff.String())
50+
}
51+
}

0 commit comments

Comments
 (0)