Skip to content

Commit

Permalink
Adding -json flag to output results to stdout in JSON format (#147)
Browse files Browse the repository at this point in the history
* Adding -json flag to output results to stdout in JSON format

* Updating user guide README

* Fixing userguide MD format

* Removig trailing space
  • Loading branch information
rickygodoy authored and mikouaj committed Nov 8, 2022
1 parent 45289d2 commit 9de26fd
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 0 deletions.
13 changes: 13 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,19 @@ policyExclusions:
The GKE Policy Automation tool produces cluster validation results to the stderr, local JSON file,
file on a GCS bucket and Pub/Sub topic.

### Console JSON output

The validation results can be displayed in the console standard output in a JSON format using the
```-json``` flag.

Example of enabling JSON standard output in a command line:

```sh
./gke-policy check \
--project my-project --location europe-west2 --name my-cluster \
-json
```

### Local JSON file

The validation results can be stored in the local file in a JSON format.
Expand Down
7 changes: 7 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ func (p *PolicyAutomationApp) LoadConfig(config *cfg.Config) (err error) {
if !p.config.SilentMode {
p.out = outputs.NewStdOutOutput()
p.collectors = []outputs.ValidationResultCollector{outputs.NewConsoleResultCollector(p.out)}

if p.config.JsonOutput {
p.out = outputs.NewSilentOutput()
p.collectors = []outputs.ValidationResultCollector{outputs.NewConsoleJsonResultCollector(outputs.NewStdOutOutput())}
}

p.clusterDumpCollectors = append(p.clusterDumpCollectors, outputs.NewOutputClusterDumpCollector(p.out))
}
if p.config.DumpFile != "" {
Expand Down Expand Up @@ -351,6 +357,7 @@ func newConfigFromFile(path string) (*cfg.Config, error) {
func newConfigFromCli(cliConfig *CliConfig) *cfg.Config {
config := &cfg.Config{}
config.SilentMode = cliConfig.SilentMode
config.JsonOutput = cliConfig.JsonOutput
config.K8SApiConfig.Enabled = cliConfig.K8SCheck
config.CredentialsFile = cliConfig.CredentialsFile
config.DumpFile = cliConfig.DumpFile
Expand Down
4 changes: 4 additions & 0 deletions internal/app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ func TestLoadConfig(t *testing.T) {
func TestNewConfigFromCli(t *testing.T) {
input := &CliConfig{
SilentMode: true,
JsonOutput: true,
CredentialsFile: "/path/to/creds.json",
ClusterName: "testCluster",
ClusterLocation: "europe-central2",
Expand All @@ -177,6 +178,9 @@ func TestNewConfigFromCli(t *testing.T) {
if config.SilentMode != input.SilentMode {
t.Errorf("silentMode = %v; want %v", config.SilentMode, input.SilentMode)
}
if config.JsonOutput != input.JsonOutput {
t.Errorf("jsonOutput = %v; want %v", config.JsonOutput, input.JsonOutput)
}
if config.CredentialsFile != input.CredentialsFile {
t.Errorf("credentialsFile = %v; want %v", config.CredentialsFile, input.CredentialsFile)
}
Expand Down
6 changes: 6 additions & 0 deletions internal/app/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
type CliConfig struct {
ConfigFile string
SilentMode bool
JsonOutput bool
K8SCheck bool
CredentialsFile string
DumpFile string
Expand Down Expand Up @@ -267,6 +268,11 @@ func getOutputFlags(config *CliConfig) []cli.Flag {
Usage: "Path to the file for storing results",
Destination: &config.OutputFile,
},
&cli.BoolFlag{
Name: "json",
Usage: "Outputs results to standard console in JSON format",
Destination: &config.JsonOutput,
},
}
}

Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type ValidateConfig func(config Config) error

type Config struct {
SilentMode bool `yaml:"silent"`
JsonOutput bool `yaml:"jsonOutput"`
DumpFile string `yaml:"dumpFile"`
CredentialsFile string `yaml:"credentialsFile"`
Clusters []ConfigCluster `yaml:"clusters"`
Expand Down
52 changes: 52 additions & 0 deletions internal/outputs/console_json_collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package outputs

import (
"github.com/google/gke-policy-automation/internal/policy"
)

type consoleJsonResultCollector struct {
out *Output
reportMapper ValidationReportMapper
}

func NewConsoleJsonResultCollector(output *Output) ValidationResultCollector {
return &consoleJsonResultCollector{
out: output,
reportMapper: NewValidationReportMapper(),
}
}

func (p *consoleJsonResultCollector) RegisterResult(results []*policy.PolicyEvaluationResult) error {
p.reportMapper.AddResults(results)
return nil
}

func (p *consoleJsonResultCollector) Close() error {

jsonResult, err := p.reportMapper.GetJsonReport()

if err != nil {
return err
}

p.out.Printf(string(jsonResult))
return nil
}

func (p *consoleJsonResultCollector) Name() string {
return "console json"
}
51 changes: 51 additions & 0 deletions internal/outputs/console_json_collector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package outputs

import (
"bytes"
"testing"

"github.com/google/gke-policy-automation/internal/policy"
)

func TestConsoleJsonResultCollector(t *testing.T) {
var buff bytes.Buffer
var expectedJson = "json string"

out := &Output{w: &buff}
reportMapperMock := &validationReportMapperMock{
addResultsFn: func(results []*policy.PolicyEvaluationResult) {},
getJsonReportFn: func() ([]byte, error) {
return []byte(expectedJson), nil
},
}

collector := &consoleJsonResultCollector{out: out, reportMapper: reportMapperMock}
err := collector.RegisterResult([]*policy.PolicyEvaluationResult{{}})
if err != nil {
t.Fatalf("err on RegisterResult = %v; want nil", err)
}
err = collector.Close()
if err != nil {
t.Fatalf("err on Close = %v; want nil", err)
}
if len(buff.String()) <= 0 {
t.Errorf("nothing was written to the output buffer")
}
if buff.String() != expectedJson {
t.Errorf("expected \"%v\" but buffer was \"%v\"", expectedJson, buff.String())
}
}

0 comments on commit 9de26fd

Please sign in to comment.