Skip to content

Commit

Permalink
feat: add json output support (#264)
Browse files Browse the repository at this point in the history
* feat: add json output support

Signed-off-by: Charles-Edouard Brétéché <[email protected]>

* codegen

Signed-off-by: Charles-Edouard Brétéché <[email protected]>

---------

Signed-off-by: Charles-Edouard Brétéché <[email protected]>
  • Loading branch information
eddycharly authored Jan 8, 2024
1 parent f5e3325 commit c42cc9b
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 9 deletions.
1 change: 1 addition & 0 deletions pkg/commands/scan/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func Command() *cobra.Command {
cmd.Flags().StringSliceVar(&command.preprocessors, "pre-process", nil, "JMESPath expression used to pre process payload")
cmd.Flags().StringSliceVar(&command.policies, "policy", nil, "Path to kyverno-json policies")
cmd.Flags().StringSliceVar(&command.selectors, "labels", nil, "Labels selectors for policies")
cmd.Flags().StringVar(&command.output, "output", "text", "Output format (text or json)")
return cmd
}
19 changes: 10 additions & 9 deletions pkg/commands/scan/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ type options struct {
preprocessors []string
policies []string
selectors []string
output string
}

func (c *options) run(cmd *cobra.Command, _ []string) error {
out := cmd.OutOrStdout()
fmt.Fprintln(out, "Loading policies ...")
out := newOutput(cmd.OutOrStdout(), c.output)
out.println("Loading policies ...")
policies, err := policy.Load(c.policies...)
if err != nil {
return err
Expand All @@ -47,15 +48,15 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
}
policies = filteredPolicies
}
fmt.Fprintln(out, "Loading payload ...")
out.println("Loading payload ...")
payload, err := payload.Load(c.payload)
if err != nil {
return err
}
if payload == nil {
return errors.New("payload is `null`")
}
fmt.Fprintln(out, "Pre processing ...")
out.println("Pre processing ...")
for _, preprocessor := range c.preprocessors {
result, err := template.Execute(context.Background(), preprocessor, payload, nil)
if err != nil {
Expand All @@ -72,22 +73,22 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
} else {
resources = append(resources, payload)
}
fmt.Fprintln(out, "Running", "(", "evaluating", len(resources), pluralize.Pluralize(len(resources), "resource", "resources"), "against", len(policies), pluralize.Pluralize(len(policies), "policy", "policies"), ")", "...")
out.println("Running", "(", "evaluating", len(resources), pluralize.Pluralize(len(resources), "resource", "resources"), "against", len(policies), pluralize.Pluralize(len(policies), "policy", "policies"), ")", "...")
e := jsonengine.New()
responses := e.Run(context.Background(), jsonengine.Request{
Resources: resources,
Policies: policies,
})
for _, response := range responses {
if response.Result == jsonengine.StatusFail {
fmt.Fprintln(out, "-", response.PolicyName, "/", response.RuleName, "/", response.Identifier, "FAILED:", response.Message)
out.println("-", response.PolicyName, "/", response.RuleName, "/", response.Identifier, "FAILED:", response.Message)
} else if response.Result == jsonengine.StatusError {
fmt.Fprintln(out, "-", response.PolicyName, "/", response.RuleName, "/", response.Identifier, "ERROR:", response.Message)
out.println("-", response.PolicyName, "/", response.RuleName, "/", response.Identifier, "ERROR:", response.Message)
} else {
// TODO: handle skip, warn
fmt.Fprintln(out, "-", response.PolicyName, "/", response.RuleName, "/", response.Identifier, "PASSED")
out.println("-", response.PolicyName, "/", response.RuleName, "/", response.Identifier, "PASSED")
}
}
fmt.Fprintln(out, "Done")
out.println("Done")
return nil
}
48 changes: 48 additions & 0 deletions pkg/commands/scan/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package scan

import (
"encoding/json"
"fmt"
"io"

jsonengine "github.com/kyverno/kyverno-json/pkg/json-engine"
)

type output interface {
println(args ...any)
responses(responses ...jsonengine.RuleResponse)
}

type textOutput struct {
out io.Writer
}

func (t *textOutput) println(args ...any) {
fmt.Fprintln(t.out, args...)
}

func (t *textOutput) responses(responses ...jsonengine.RuleResponse) {
}

type jsonOutput struct {
out io.Writer
}

func (t *jsonOutput) println(args ...any) {
}

func (t *jsonOutput) responses(responses ...jsonengine.RuleResponse) {
payload, err := json.MarshalIndent(&jsonengine.Response{Results: responses}, "", " ")
if err != nil {
fmt.Fprintln(t.out, err)
} else {
fmt.Fprintln(t.out, string(payload))
}
}

func newOutput(out io.Writer, format string) output {
if format == "json" {
return &jsonOutput{out: out}
}
return &textOutput{out: out}
}
1 change: 1 addition & 0 deletions website/docs/cli/commands/kyverno-json_scan.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ kyverno-json scan [flags]
```
-h, --help help for scan
--labels strings Labels selectors for policies
--output string Output format (text or json) (default "text")
--payload string Path to payload (json or yaml file)
--policy strings Path to kyverno-json policies
--pre-process strings JMESPath expression used to pre process payload
Expand Down

0 comments on commit c42cc9b

Please sign in to comment.