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...), 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(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(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.Printf("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(file) if err != nil { return nil, err } expressions = append(expressions, expression) } if len(expressions) == 0 { fmt.Println("Reading from terminal input.") fmt.Println("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(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.Println("#", expression) fmt.Println(parsed) return nil }