Skip to content

Commit

Permalink
✨ Use Cobra for cli (#274)
Browse files Browse the repository at this point in the history
Signed-off-by: Emily McMullan <[email protected]>
  • Loading branch information
eemcmullan authored Aug 9, 2023
1 parent 6c6dbb5 commit 79db99c
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 51 deletions.
95 changes: 60 additions & 35 deletions cmd/analyzer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/konveyor/analyzer-lsp/provider/lib"
"github.com/konveyor/analyzer-lsp/tracing"
"github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)

Expand All @@ -25,25 +25,50 @@ const (
)

var (
settingsFile = flag.String("provider-settings", "provider_settings.json", "path to the provider settings")
rulesFile = flag.StringArray("rules", []string{"rule-example.yaml"}, "filename or directory containing rule files")
outputViolations = flag.String("output-file", "output.yaml", "filepath to to store rule violations")
errorOnViolations = flag.Bool("error-on-violation", false, "exit with 3 if any violation are found will also print violations to console")
labelSelector = flag.String("label-selector", "", "an expression to select rules based on labels")
depLabelSelector = flag.String("dep-label-selector", "", "an expression to select dependencies based on labels. This will filter out the violations from these dependencies as well these dependencies when matching dependency conditions.")
logLevel = flag.Int("verbose", 9, "level for logging output")
enableJaeger = flag.Bool("enable-jaeger", false, "enable tracer exports to jaeger endpoint")
jaegerEndpoint = flag.String("jaeger-endpoint", "http://localhost:14268/api/traces", "jaeger endpoint to collect tracing data")
limitIncidents = flag.Int("limit-incidents", 1500, "Set this to the limit incidents that a given rule can give, zero means no limit")
limitCodeSnips = flag.Int("limit-code-snips", 20, "limit the number code snippets that are retrieved for a file while evaluating a rule, 0 means no limit")
analysisMode = flag.String("analysis-mode", "", "select one of full or source-only to tell the providers what to analyize. This can be given on a per provider setting, but this flag will override")
noDependencyRules = flag.Bool("no-dependency-rules", false, "Disable dependency analysis rules")
settingsFile string
rulesFile []string
outputViolations string
errorOnViolations bool
labelSelector string
depLabelSelector string
logLevel int
enableJaeger bool
jaegerEndpoint string
limitIncidents int
limitCodeSnips int
analysisMode string
noDependencyRules bool

rootCmd = &cobra.Command{
Use: "analyze",
Short: "Tool for working with analyzer-lsp",
Run: func(c *cobra.Command, args []string) {},
}
)

func init() {
rootCmd.Flags().StringVar(&settingsFile, "settings-file", "provider_settings.json", "path to the provider settings")
rootCmd.Flags().StringArrayVar(&rulesFile, "rules-file", []string{"rule-example.yaml"}, "filename or directory containing rule files")
rootCmd.Flags().StringVar(&outputViolations, "output-file", "output.yaml", "filepath to to store rule violations")
rootCmd.Flags().BoolVar(&errorOnViolations, "error-on-violation", false, "exit with 3 if any violation are found will also print violations to console")
rootCmd.Flags().StringVar(&labelSelector, "label-selector", "", "an expression to select rules based on labels")
rootCmd.Flags().StringVar(&depLabelSelector, "dep-label-selector", "", "an expression to select dependencies based on labels. This will filter out the violations from these dependencies as well these dependencies when matching dependency conditions")
rootCmd.Flags().IntVar(&logLevel, "verbose", 9, "level for logging output")
rootCmd.Flags().BoolVar(&enableJaeger, "enable-jaeger", false, "enable tracer exports to jaeger endpoint")
rootCmd.Flags().StringVar(&jaegerEndpoint, "jaeger-endpoint", "http://localhost:14268/api/traces", "jaeger endpoint to collect tracing data")
rootCmd.Flags().IntVar(&limitIncidents, "limit-incidents", 1500, "Set this to the limit incidents that a given rule can give, zero means no limit")
rootCmd.Flags().IntVar(&limitCodeSnips, "limit-code-snips", 20, "limit the number code snippets that are retrieved for a file while evaluating a rule, 0 means no limit")
rootCmd.Flags().StringVar(&analysisMode, "analysis-mode", "", "select one of full or source-only to tell the providers what to analyize. This can be given on a per provider setting, but this flag will override")
rootCmd.Flags().BoolVar(&noDependencyRules, "no-dependency-rules", false, "Disable dependency analysis rules")
}

func main() {
if err := rootCmd.Execute(); err != nil {
println(err.Error())
}

// This will globally prevent the yaml library from auto-wrapping lines at 80 characters
yaml.FutureLineWrap()
flag.Parse()

err := validateFlags()
if err != nil {
Expand All @@ -55,16 +80,16 @@ func main() {
logrusLog.SetOutput(os.Stdout)
logrusLog.SetFormatter(&logrus.TextFormatter{})
// need to do research on mapping in logrusr to level here TODO
logrusLog.SetLevel(logrus.Level(*logLevel))
logrusLog.SetLevel(logrus.Level(logLevel))

log := logrusr.New(logrusLog)

ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

selectors := []engine.RuleSelector{}
if labelSelector != nil && *labelSelector != "" {
selector, err := labels.NewLabelSelector[*engine.RuleMeta](*labelSelector)
if labelSelector != "" {
selector, err := labels.NewLabelSelector[*engine.RuleMeta](labelSelector)
if err != nil {
log.Error(err, "failed to create label selector from expression", "selector", labelSelector)
os.Exit(1)
Expand All @@ -73,17 +98,17 @@ func main() {
}

var dependencyLabelSelector *labels.LabelSelector[*konveyor.Dep]
if depLabelSelector != nil && *depLabelSelector != "" {
dependencyLabelSelector, err = labels.NewLabelSelector[*konveyor.Dep](*depLabelSelector)
if depLabelSelector != "" {
dependencyLabelSelector, err = labels.NewLabelSelector[*konveyor.Dep](depLabelSelector)
if err != nil {
log.Error(err, "failed to create label selector from expression", "selector", labelSelector)
os.Exit(1)
}
}

tracerOptions := tracing.Options{
EnableJaeger: *enableJaeger,
JaegerEndpoint: *jaegerEndpoint,
EnableJaeger: enableJaeger,
JaegerEndpoint: jaegerEndpoint,
}
tp, err := tracing.InitTracerProvider(log, tracerOptions)
if err != nil {
Expand All @@ -97,7 +122,7 @@ func main() {
defer span.End()

// Get the configs
configs, err := provider.GetConfig(*settingsFile)
configs, err := provider.GetConfig(settingsFile)
if err != nil {
log.Error(err, "unable to get configuration")
os.Exit(1)
Expand All @@ -107,18 +132,18 @@ func main() {
eng := engine.CreateRuleEngine(ctx,
10,
log,
engine.WithIncidentLimit(*limitIncidents),
engine.WithCodeSnipLimit(*limitCodeSnips),
engine.WithIncidentLimit(limitIncidents),
engine.WithCodeSnipLimit(limitCodeSnips),
)

providers := map[string]provider.InternalProviderClient{}

for _, config := range configs {
// IF analsyis mode is set from the CLI, then we will override this for each init config
if *analysisMode != "" {
if analysisMode != "" {
inits := []provider.InitConfig{}
for _, i := range config.InitConfig {
i.AnalysisMode = provider.AnalysisMode(*analysisMode)
i.AnalysisMode = provider.AnalysisMode(analysisMode)
inits = append(inits, i)
}
config.InitConfig = inits
Expand All @@ -140,12 +165,12 @@ func main() {
parser := parser.RuleParser{
ProviderNameToClient: providers,
Log: log.WithName("parser"),
NoDependencyRules: *noDependencyRules,
NoDependencyRules: noDependencyRules,
DepLabelSelector: dependencyLabelSelector,
}
ruleSets := []engine.RuleSet{}
needProviders := map[string]provider.InternalProviderClient{}
for _, f := range *rulesFile {
for _, f := range rulesFile {
internRuleSet, internNeedProviders, err := parser.LoadRules(f)
if err != nil {
log.WithValues("fileName", f).Error(err, "unable to parse all the rules for ruleset")
Expand Down Expand Up @@ -177,28 +202,28 @@ func main() {

// Write results out to CLI
b, _ := yaml.Marshal(rulesets)
if *errorOnViolations && len(rulesets) != 0 {
if errorOnViolations && len(rulesets) != 0 {
fmt.Printf("%s", string(b))
os.Exit(EXIT_ON_ERROR_CODE)
}

os.WriteFile(*outputViolations, b, 0644)
os.WriteFile(outputViolations, b, 0644)
}

func validateFlags() error {
_, err := os.Stat(*settingsFile)
_, err := os.Stat(settingsFile)
if err != nil {
return fmt.Errorf("unable to find provider settings file")
}

for _, f := range *rulesFile {
for _, f := range rulesFile {
_, err = os.Stat(f)
if err != nil {
return fmt.Errorf("unable to find rule path or file")
}
}
m := provider.AnalysisMode(strings.ToLower(*analysisMode))
if *analysisMode != "" && !(m == provider.FullAnalysisMode || m == provider.SourceOnlyAnalysisMode) {
m := provider.AnalysisMode(strings.ToLower(analysisMode))
if analysisMode != "" && !(m == provider.FullAnalysisMode || m == provider.SourceOnlyAnalysisMode) {
return fmt.Errorf("must select one of %s or %s for analysis mode", provider.FullAnalysisMode, provider.SourceOnlyAnalysisMode)
}

Expand Down
45 changes: 30 additions & 15 deletions cmd/dep/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"flag"
"fmt"
"os"
"sort"
Expand All @@ -13,24 +12,40 @@ import (
"github.com/konveyor/analyzer-lsp/provider"
"github.com/konveyor/analyzer-lsp/provider/lib"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)

var (
providerSettings = flag.String("provider-settings", "provider_settings.json", "path to provider settings file")
treeOutput = flag.Bool("tree", false, "output dependencies as a tree")
outputFile = flag.String("output-file", "output.yaml", "path to output file")
depLabelSelector = flag.String("dep-label-selector", "", "an expression to select dependencies based on labels provided by the provider")
providerSettings string
treeOutput bool
outputFile string
depLabelSelector string

rootCmd = &cobra.Command{
Use: "analyze",
Short: "Tool for working with analyzer-lsp",
Run: func(c *cobra.Command, args []string) {},
}
)

func init() {
rootCmd.Flags().StringVar(&providerSettings, "provider-settings", "provider_settings.json", "path to the provider settings")
rootCmd.Flags().BoolVar(&treeOutput, "tree", false, "output dependencies as a tree")
rootCmd.Flags().StringVar(&outputFile, "output-file", "output.yaml", "path to output file")
rootCmd.Flags().StringVar(&depLabelSelector, "dep-label-selector", "", "an expression to select dependencies based on labels provided by the provider")
}

func main() {
if err := rootCmd.Execute(); err != nil {
println(err.Error())
}

logrusLog := logrus.New()
logrusLog.SetOutput(os.Stdout)
logrusLog.SetFormatter(&logrus.TextFormatter{})
log := logrusr.New(logrusLog)

flag.Parse()

err := validateFlags()
if err != nil {
log.Error(err, "failed to validate input flags")
Expand All @@ -43,7 +58,7 @@ func main() {
providers := map[string]provider.Client{}

// Get the configs
configs, err := provider.GetConfig(*providerSettings)
configs, err := provider.GetConfig(providerSettings)
if err != nil {
log.Error(err, "unable to get configuration")
os.Exit(1)
Expand Down Expand Up @@ -78,7 +93,7 @@ func main() {
continue
}

if *treeOutput {
if treeOutput {
deps, err := prov.GetDependenciesDAG()
if err != nil {
log.Error(err, "failed to get list of dependencies for provider", "provider", name)
Expand All @@ -99,8 +114,8 @@ func main() {
}
for u, ds := range deps {
newDeps := ds
if depLabelSelector != nil && *depLabelSelector != "" {
l, err := labels.NewLabelSelector[*konveyor.Dep](*depLabelSelector)
if depLabelSelector != "" {
l, err := labels.NewLabelSelector[*konveyor.Dep](depLabelSelector)
if err != nil {
panic(err)
}
Expand All @@ -124,7 +139,7 @@ func main() {
}

var b []byte
if *treeOutput {
if treeOutput {
b, err = yaml.Marshal(depsTree)
if err != nil {
log.Error(err, "failed to marshal dependency data as yaml")
Expand All @@ -149,15 +164,15 @@ func main() {

fmt.Printf("%s", string(b))

err = os.WriteFile(*outputFile, b, 0644)
err = os.WriteFile(outputFile, b, 0644)
if err != nil {
log.Error(err, "failed to write dependencies to output file", "file", *outputFile)
log.Error(err, "failed to write dependencies to output file", "file", outputFile)
os.Exit(1)
}
}

func validateFlags() error {
_, err := os.Stat(*providerSettings)
_, err := os.Stat(providerSettings)
if err != nil {
return fmt.Errorf("unable to find provider settings file")
}
Expand Down
7 changes: 6 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ require (
gopkg.in/yaml.v2 v2.4.0
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/cobra v1.7.0 // indirect
)

require (
github.com/antchfx/xpath v1.2.4
github.com/cbroglie/mustache v1.4.0
github.com/cbroglie/mustache v1.3.0
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/swag v0.19.5 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY=
github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/bombsimon/logrusr/v3 v3.0.0 h1:tcAoLfuAhKP9npBxWzSdpsvKPQt1XV02nSf2lZA82TQ=
github.com/bombsimon/logrusr/v3 v3.0.0/go.mod h1:PksPPgSFEL2I52pla2glgCyyd2OqOHAnFF5E+g8Ixco=
github.com/cbroglie/mustache v1.3.0 h1:sj24GVYl8G7MH4b3zaROGsZnF8X79JqtjMx8/6H/nXM=
github.com/cbroglie/mustache v1.3.0/go.mod h1:w58RIHjw/L7DPyRX2CcCTduNmcP1dvztaHP72ciSfh0=
github.com/cbroglie/mustache v1.4.0 h1:Azg0dVhxTml5me+7PsZ7WPrQq1Gkf3WApcHMjMprYoU=
github.com/cbroglie/mustache v1.4.0/go.mod h1:SS1FTIghy0sjse4DUVGV1k/40B1qE1XkD9DtDsHo9iM=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -38,6 +41,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
Expand All @@ -54,10 +59,13 @@ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1H
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down

0 comments on commit 79db99c

Please sign in to comment.