github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/inspector/cmd/rules.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "strings" 8 9 "github.com/apprenda/kismatic/pkg/inspector/rule" 10 "github.com/spf13/cobra" 11 ) 12 13 // NewCmdRules returns the "rules" command 14 func NewCmdRules(out io.Writer) *cobra.Command { 15 var file string 16 cmd := &cobra.Command{ 17 Use: "rules", 18 Short: "Manipulate the inspector's rules", 19 RunE: func(cmd *cobra.Command, args []string) error { 20 return cmd.Help() 21 }, 22 } 23 cmd.PersistentFlags().StringVarP(&file, "file", "f", "inspector-rules.yaml", "file where inspector rules are to be written") 24 cmd.AddCommand(NewCmdDumpRules(out, file)) 25 cmd.AddCommand(NewCmdValidateRules(out, file)) 26 return cmd 27 } 28 29 // NewCmdDumpRules returns the "dump" command 30 func NewCmdDumpRules(out io.Writer, file string) *cobra.Command { 31 var overwrite bool 32 cmd := &cobra.Command{ 33 Use: "dump", 34 Short: "Dump the inspector rules to a file", 35 RunE: func(cmd *cobra.Command, args []string) error { 36 if _, err := os.Stat(file); err == nil && !overwrite { 37 return fmt.Errorf("%q already exists. Use --overwrite to overwrite it", file) 38 } 39 f, err := os.Create(file) 40 if err != nil { 41 return fmt.Errorf("error creating %q: %v", file, err) 42 } 43 if err := rule.DumpDefaultRules(f); err != nil { 44 return fmt.Errorf("error dumping rules: %v", err) 45 } 46 return nil 47 }, 48 } 49 cmd.Flags().BoolVar(&overwrite, "overwrite", false, "overwrite the destination file if it exists") 50 return cmd 51 } 52 53 func NewCmdValidateRules(out io.Writer, file string) *cobra.Command { 54 var additionalVars []string 55 cmd := &cobra.Command{ 56 Use: "validate", 57 Short: "Validate the inspector rules", 58 RunE: func(cmd *cobra.Command, args []string) error { 59 if _, err := os.Stat(file); os.IsNotExist(err) { 60 return fmt.Errorf("%q does not exist", file) 61 } 62 additionalVarsM := make(map[string]string) 63 for _, v := range additionalVars { 64 kv := strings.Split(v, "=") 65 if len(kv) != 2 { 66 return fmt.Errorf("invalid key-value %q", v) 67 } 68 additionalVarsM[kv[0]] = kv[1] 69 } 70 rules, err := rule.ReadFromFile(file, additionalVarsM) 71 if err != nil { 72 return err 73 } 74 if !validateRules(out, rules) { 75 return fmt.Errorf("invalid rules found in %q", file) 76 } 77 fmt.Fprintf(out, "Rules are valid\n") 78 return nil 79 }, 80 } 81 cmd.Flags().StringSliceVar(&additionalVars, "additional-vars", []string{}, "provide a key=value list to template ruleset") 82 return cmd 83 } 84 85 // validates rules, printing error messages to the console 86 func validateRules(out io.Writer, rules []rule.Rule) bool { 87 allOK := true 88 for i, r := range rules { 89 errs := r.Validate() 90 if len(errs) > 0 { 91 allOK = false 92 fmt.Fprintf(out, "%s (Rule #%d):\n", r.GetRuleMeta().Kind, i+1) 93 for _, e := range errs { 94 fmt.Fprintf(out, "- %v\n", e) 95 } 96 fmt.Fprintln(out, "") 97 } 98 } 99 return allOK 100 }