diff --git a/README.md b/README.md index 74739813..6d3fe0d6 100644 --- a/README.md +++ b/README.md @@ -78,12 +78,12 @@ $./kubent -h Usage of ./kubent: -a, --additional-kind strings additional kinds of resources to report in Kind.version.group.com format -c, --cluster enable Cluster collector (default true) - -d, --debug enable debug logging -e, --exit-error exit with non-zero code when issues are found -f, --filename strings manifests to check, use - for stdin --helm2 enable Helm v2 collector (default true) --helm3 enable Helm v3 collector (default true) -k, --kubeconfig string path to the kubeconfig file (default "/Users/stepan/.kube/config") + -l, --loglevel string set log level (trace, debug, info, warn, error, fatal, panic, disabled) -o, --output string output format - [text|json] (default "text") ``` diff --git a/cmd/kubent/main.go b/cmd/kubent/main.go index e3a9ce4b..46e9e6fa 100644 --- a/cmd/kubent/main.go +++ b/cmd/kubent/main.go @@ -81,16 +81,13 @@ func main() { exitCode := EXIT_CODE_FAIL_GENERIC log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) - zerolog.SetGlobalLevel(zerolog.InfoLevel) config, err := config.NewFromFlags() if err != nil { log.Fatal().Err(err).Msg("failed to parse config flags") } - if config.Debug { - zerolog.SetGlobalLevel(zerolog.DebugLevel) - } + zerolog.SetGlobalLevel(zerolog.Level(config.LogLevel)) log.Info().Msg(">>> Kube No Trouble `kubent` <<<") log.Info().Msgf("version %s (git sha %s)", version, gitSha) diff --git a/cmd/kubent/main_test.go b/cmd/kubent/main_test.go index 78d1da75..98b54197 100644 --- a/cmd/kubent/main_test.go +++ b/cmd/kubent/main_test.go @@ -9,16 +9,17 @@ import ( "github.com/doitintl/kube-no-trouble/pkg/collector" "github.com/doitintl/kube-no-trouble/pkg/config" + "github.com/rs/zerolog" ) func TestInitCollectors(t *testing.T) { testConfig := config.Config{ Filenames: []string{"../../fixtures/deployment-v1beta1.yaml"}, Cluster: false, - Debug: false, Helm2: false, Helm3: false, Kubeconfig: "test", + LogLevel: config.ZeroLogLevel(zerolog.ErrorLevel), Output: "test", } diff --git a/go.mod b/go.mod index 6e45693f..a5ed225f 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/jmoiron/sqlx v1.2.0 // indirect github.com/lib/pq v1.3.0 // indirect github.com/open-policy-agent/opa v0.27.1 - github.com/rs/zerolog v1.21.0 + github.com/rs/zerolog v1.21.1-0.20210413053206-582f0cf0e39b github.com/rubenv/sql-migrate v0.0.0-20200402132117-435005d389bc // indirect github.com/spf13/pflag v1.0.5 helm.sh/helm v2.17.0+incompatible diff --git a/go.sum b/go.sum index 3baf8e0b..9c1b5aef 100644 --- a/go.sum +++ b/go.sum @@ -532,6 +532,8 @@ github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.21.0 h1:Q3vdXlfLNT+OftyBHsU0Y445MD+8m8axjKgf2si0QcM= github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= +github.com/rs/zerolog v1.21.1-0.20210413053206-582f0cf0e39b h1:lZjlZ6/ExLhIqPOmlh0dVJnBbiKokcjffr022PlkSSo= +github.com/rs/zerolog v1.21.1-0.20210413053206-582f0cf0e39b/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= github.com/rubenv/sql-migrate v0.0.0-20200402132117-435005d389bc h1:+2DdDcxVYlarHjYcZTt8dZ4Ec8cXZirzL5ko0mkKPjU= github.com/rubenv/sql-migrate v0.0.0-20200402132117-435005d389bc/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= diff --git a/pkg/config/config.go b/pkg/config/config.go index c5e33de9..f19d4683 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -7,36 +7,55 @@ import ( "strings" "unicode" - "github.com/rs/zerolog/log" + "github.com/rs/zerolog" flag "github.com/spf13/pflag" "k8s.io/client-go/util/homedir" ) +type ZeroLogLevel int8 + +func (l ZeroLogLevel) String() string { + return zerolog.Level(l).String() +} + +func (l *ZeroLogLevel) Set(s string) error { + level, err := zerolog.ParseLevel(s) + if err != nil { + return err + } + *l = ZeroLogLevel(level) + return nil +} + +func (l ZeroLogLevel) Type() string { + return "string" +} + type Config struct { AdditionalKinds []string Cluster bool - Debug bool ExitError bool Filenames []string Helm2 bool Helm3 bool Kubeconfig string + LogLevel ZeroLogLevel Output string } func NewFromFlags() (*Config, error) { - config := Config{} + config := Config{LogLevel: ZeroLogLevel(zerolog.InfoLevel)} home := homedir.HomeDir() flag.StringSliceVarP(&config.AdditionalKinds, "additional-kind", "a", []string{}, "additional kinds of resources to report in Kind.version.group.com format") flag.BoolVarP(&config.Cluster, "cluster", "c", true, "enable Cluster collector") - flag.BoolVarP(&config.Debug, "debug", "d", false, "enable debug logging") flag.BoolVarP(&config.ExitError, "exit-error", "e", false, "exit with non-zero code when issues are found") flag.BoolVar(&config.Helm2, "helm2", true, "enable Helm v2 collector") flag.BoolVar(&config.Helm3, "helm3", true, "enable Helm v3 collector") flag.StringSliceVarP(&config.Filenames, "filename", "f", []string{}, "manifests to check, use - for stdin") flag.StringVarP(&config.Kubeconfig, "kubeconfig", "k", envOrString("KUBECONFIG", filepath.Join(home, ".kube", "config")), "path to the kubeconfig file") flag.StringVarP(&config.Output, "output", "o", "text", "output format - [text|json]") + flag.VarP(&config.LogLevel, "log-level", "l", "set log level (trace, debug, info, warn, error, fatal, panic, disabled)") flag.Parse() @@ -60,7 +79,6 @@ func envOrString(env string, def string) string { func validateAdditionalResources(resources []string) error { for _, r := range resources { parts := strings.Split(r, ".") - log.Debug().Msgf("parts: %+v", parts) if len(parts) < 4 { return fmt.Errorf("failed to parse additional Kind, full form Kind.version.group.com is expected, instead got: %s", r) } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index cc8ec000..1b366db5 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -8,6 +8,39 @@ import ( "k8s.io/client-go/util/homedir" ) +func TestValidLogLevelFromFlags(t *testing.T) { + oldArgs := os.Args[1] + defer func() { os.Args[1] = oldArgs }() + + var validLevels = []string{"trace", "debug", "info", "warn", "error", "fatal", "panic", "", "disabled"} + for i, level := range validLevels { + // reset for testing + pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) + + os.Args[1] = "--log-level=" + level + config, err := NewFromFlags() + + if err != nil { + t.Errorf("Flags parsing failed %s", err) + } + + expected := ZeroLogLevel(i - 1) + actual := config.LogLevel + + if actual != expected { + t.Errorf("Config not parsed correctly: %s \nactual %d, expected %d", level, actual, expected) + } + } +} + +func TestInvalidLogLevelFromFlags(t *testing.T) { + var testLevel ZeroLogLevel + + if err := testLevel.Set("bad"); err == nil { + t.Errorf("Should not parse invalid flag") + } +} + func TestNewFromFlags(t *testing.T) { // reset for testing pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) @@ -50,7 +83,6 @@ func TestNewFromFlagsKubeconfigHome(t *testing.T) { pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) expected := homedir.HomeDir() + "/.kube/config" - err := os.Unsetenv("KUBECONFIG") if err != nil { t.Errorf("failed to unset KUBECONFIG env variable: %s", err) @@ -75,7 +107,7 @@ func TestEnvOrStringVariable(t *testing.T) { i := envOrString("FOO", "default") if i != "1" { - t.Errorf("Expected to get env variable, got %s insteadt", i) + t.Errorf("Expected to get env variable, got %s instead", i) } }