github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/inspector/cmd/client.go (about)

     1  package cmd
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  
     9  	"github.com/apprenda/kismatic/pkg/inspector"
    10  	"github.com/spf13/cobra"
    11  )
    12  
    13  type clientOpts struct {
    14  	outputType          string
    15  	nodeRoles           string
    16  	rulesFile           string
    17  	targetNode          string
    18  	useUpgradeDefaults  bool
    19  	additionalVariables map[string]string
    20  }
    21  
    22  var clientExample = `# Run the inspector against an etcd node
    23  kismatic-inspector client 10.0.1.24:9090 --node-roles etcd
    24  
    25  # Run the inspector against a remote node, and ask for JSON output
    26  kismatic-inspector client 10.0.1.24:9090 --node-roles etcd -o json
    27  
    28  # Run the inspector against a remote node using a custom rules file
    29  kismatic-inspector client 10.0.1.24:9090 -f inspector-rules.yaml --node-roles etcd`
    30  
    31  // NewCmdClient returns the "client" command
    32  func NewCmdClient(out io.Writer) *cobra.Command {
    33  	opts := clientOpts{}
    34  	var additionalVars []string
    35  	cmd := &cobra.Command{
    36  		Use:     "client HOST:PORT",
    37  		Short:   "Run the inspector against a remote inspector server.",
    38  		Example: clientExample,
    39  		RunE: func(cmd *cobra.Command, args []string) error {
    40  			if len(args) != 1 {
    41  				return cmd.Usage()
    42  			}
    43  			// Set the target node as the first argument
    44  			opts.targetNode = args[0]
    45  			opts.additionalVariables = make(map[string]string)
    46  			for _, v := range additionalVars {
    47  				kv := strings.Split(v, "=")
    48  				if len(kv) != 2 {
    49  					return fmt.Errorf("invalid key=value %q", v)
    50  				}
    51  				opts.additionalVariables[kv[0]] = kv[1]
    52  			}
    53  			return runClient(out, opts)
    54  		},
    55  	}
    56  	cmd.Flags().StringVarP(&opts.outputType, "output", "o", "table", "set the result output type. Options are 'json', 'table'")
    57  	cmd.Flags().StringVar(&opts.nodeRoles, "node-roles", "", "comma-separated list of the node's roles. Valid roles are 'etcd', 'master', 'worker'")
    58  	cmd.Flags().StringVarP(&opts.rulesFile, "file", "f", "", "the path to an inspector rules file. If blank, the inspector uses the default rules")
    59  	cmd.Flags().BoolVarP(&opts.useUpgradeDefaults, "upgrade", "u", false, "use defaults for upgrade, rather than install")
    60  	cmd.Flags().StringSliceVar(&additionalVars, "additional-vars", []string{}, "key=value pairs separated by ',' to template ruleset")
    61  	return cmd
    62  }
    63  
    64  func runClient(out io.Writer, opts clientOpts) error {
    65  	if err := validateOutputType(opts.outputType); err != nil {
    66  		return err
    67  	}
    68  	if opts.nodeRoles == "" {
    69  		return fmt.Errorf("--node-roles is required")
    70  	}
    71  	roles, err := getNodeRoles(opts.nodeRoles)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	c, err := inspector.NewClient(opts.targetNode, roles)
    76  	if err != nil {
    77  		return fmt.Errorf("error creating inspector client: %v", err)
    78  	}
    79  	rules, err := getRulesFromFileOrDefault(out, opts.rulesFile, opts.useUpgradeDefaults, opts.additionalVariables)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	results, err := c.ExecuteRules(rules)
    85  	if err != nil {
    86  		return fmt.Errorf("error running inspector against remote node: %v", err)
    87  	}
    88  	if err := printResults(out, results, opts.outputType); err != nil {
    89  		return err
    90  	}
    91  	for _, r := range results {
    92  		if !r.Success {
    93  			return errors.New("inspector rules failed")
    94  		}
    95  	}
    96  	return nil
    97  }