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  }