mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
* chore: add cli unit tests Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * chore: add cli commands unit tests Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
101 lines
2.8 KiB
Go
101 lines
2.8 KiB
Go
package parse
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
gojmespath "github.com/kyverno/go-jmespath"
|
|
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/command"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func Command() *cobra.Command {
|
|
var files []string
|
|
cmd := &cobra.Command{
|
|
Use: "parse [-f file|expression]...",
|
|
Short: command.FormatDescription(true, websiteUrl, false, description...),
|
|
Long: command.FormatDescription(false, websiteUrl, false, description...),
|
|
Example: command.FormatExamples(examples...),
|
|
SilenceErrors: true,
|
|
SilenceUsage: true,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
expressions, err := loadExpressions(cmd, args, files)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, expression := range expressions {
|
|
if err := printAst(cmd.OutOrStdout(), expression); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
cmd.Flags().StringSliceVarP(&files, "file", "f", nil, "Read input from a JSON or YAML file instead of stdin")
|
|
return cmd
|
|
}
|
|
|
|
func readFile(reader io.Reader) (string, error) {
|
|
data, err := io.ReadAll(reader)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(data), nil
|
|
}
|
|
|
|
func loadFile(cmd *cobra.Command, file string) (string, error) {
|
|
reader, err := os.Open(filepath.Clean(file))
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed open file %s: %v", file, err)
|
|
}
|
|
defer func() {
|
|
if err := reader.Close(); err != nil {
|
|
fmt.Fprintf(cmd.OutOrStdout(), "Error closing file: %s\n", err)
|
|
}
|
|
}()
|
|
content, err := readFile(reader)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed read file %s: %v", file, err)
|
|
}
|
|
return content, nil
|
|
}
|
|
|
|
func loadExpressions(cmd *cobra.Command, args []string, files []string) ([]string, error) {
|
|
var expressions []string
|
|
expressions = append(expressions, args...)
|
|
for _, file := range files {
|
|
expression, err := loadFile(cmd, file)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
expressions = append(expressions, expression)
|
|
}
|
|
if len(expressions) == 0 {
|
|
fmt.Fprintln(cmd.OutOrStdout(), "Reading from terminal input.")
|
|
fmt.Fprintln(cmd.OutOrStdout(), "Enter a jmespath expression and hit Ctrl+D.")
|
|
data, err := readFile(cmd.InOrStdin())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read file STDIN: %v", err)
|
|
}
|
|
expressions = append(expressions, data)
|
|
}
|
|
return expressions, nil
|
|
}
|
|
|
|
// The following function has been adapted from
|
|
// https://github.com/jmespath/jp/blob/54882e03bd277fc4475a677fab1d35eaa478b839/jp.go
|
|
func printAst(out io.Writer, expression string) error {
|
|
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.Fprintln(out, "#", expression)
|
|
fmt.Fprintln(out, parsed)
|
|
return nil
|
|
}
|