1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-07 08:26:53 +00:00
kyverno/cmd/cli/kubectl-kyverno/jp/jp_command.go
Eng Zer Jun f40a3bc8f5
refactor: move from io/ioutil to io and os packages (#4752)
The io/ioutil package has been deprecated as of Go 1.16 [1]. This commit
replaces the existing io/ioutil functions with their new definitions in
io and os packages.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2022-09-30 12:55:19 +05:30

130 lines
4 KiB
Go

package jp
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
gojmespath "github.com/jmespath/go-jmespath"
jmespath "github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"
)
var applyHelp = `
For more information visit: https://kyverno.io/docs/writing-policies/jmespath/
`
// Command returns jp command
func Command() *cobra.Command {
var compact, unquoted, ast, listFunctions bool
var filename, exprFile string
cmd := &cobra.Command{
Use: "jp",
Short: "Provides a command-line interface to JMESPath, enhanced with Kyverno specific custom functions",
SilenceUsage: true,
Example: applyHelp,
RunE: func(cmd *cobra.Command, args []string) error {
if listFunctions {
printFunctionList()
return nil
}
// The following function has been adapted from
// https://github.com/jmespath/jp/blob/54882e03bd277fc4475a677fab1d35eaa478b839/jp.go
var expression string
if exprFile != "" {
byteExpr, err := os.ReadFile(filepath.Clean(exprFile))
if err != nil {
return fmt.Errorf("error opening expression file: %w", err)
}
expression = string(byteExpr)
} else {
if len(args) == 0 {
return fmt.Errorf("must provide at least one argument")
}
expression = args[0]
}
if ast {
parser := gojmespath.NewParser()
parsed, err := parser.Parse(expression)
if err != nil {
if syntaxError, ok := err.(gojmespath.SyntaxError); ok {
return fmt.Errorf("%w\n%s",
syntaxError,
syntaxError.HighlightLocation())
}
return err
}
fmt.Printf("%s", parsed)
return nil
}
var input interface{}
if filename != "" {
f, err := os.ReadFile(filepath.Clean(filename))
if err != nil {
return fmt.Errorf("error opening input file: %w", err)
}
if err := yaml.Unmarshal(f, &input); err != nil {
return fmt.Errorf("error parsing input json: %w", err)
}
} else {
f, err := io.ReadAll(os.Stdin)
if err != nil {
return fmt.Errorf("error opening input file: %w", err)
}
if err := yaml.Unmarshal(f, &input); err != nil {
return fmt.Errorf("error parsing input json: %w", err)
}
}
jp, err := jmespath.New(expression)
if err != nil {
return fmt.Errorf("failed to compile JMESPath: %s, error: %v", expression, err)
}
result, err := jp.Search(input)
if err != nil {
if syntaxError, ok := err.(gojmespath.SyntaxError); ok {
return fmt.Errorf("%s\n%s",
syntaxError,
syntaxError.HighlightLocation())
}
return fmt.Errorf("error evaluating JMESPath expression: %w", err)
}
converted, isString := result.(string)
if unquoted && isString {
fmt.Println(converted)
} else {
var toJSON []byte
if compact {
toJSON, err = json.Marshal(result)
} else {
toJSON, err = json.MarshalIndent(result, "", " ")
}
if err != nil {
return fmt.Errorf("error marshalling result to JSON: %w", err)
}
fmt.Println(string(toJSON))
}
return nil
},
}
cmd.Flags().BoolVarP(&compact, "compact", "c", false, "Produce compact JSON output that omits nonessential whitespace")
cmd.Flags().BoolVarP(&listFunctions, "list-functions", "l", false, "Output a list of custom JMESPath functions in Kyverno")
cmd.Flags().BoolVarP(&unquoted, "unquoted", "u", false, "If the final result is a string, it will be printed without quotes")
cmd.Flags().BoolVar(&ast, "ast", false, "Only print the AST of the parsed expression. Do not rely on this output, only useful for debugging purposes")
cmd.Flags().StringVarP(&exprFile, "expr-file", "e", "", "Read JMESPath expression from the specified file")
cmd.Flags().StringVarP(&filename, "filename", "f", "", "Read input from a JSON or YAML file instead of stdin")
return cmd
}
func printFunctionList() {
functions := []string{}
for _, function := range jmespath.GetFunctions() {
functions = append(functions, function.String())
}
sort.Strings(functions)
fmt.Println(strings.Join(functions, "\n"))
}