diff --git a/cmd/kubent/main.go b/cmd/kubent/main.go index ef3fdd95..03216a4b 100644 --- a/cmd/kubent/main.go +++ b/cmd/kubent/main.go @@ -1,7 +1,9 @@ package main import ( + "flag" "fmt" + "io" "os" "github.com/doitintl/kube-no-trouble/pkg/collector" @@ -16,6 +18,7 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/azure" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" + "k8s.io/klog/v2" ) var ( @@ -97,6 +100,13 @@ func main() { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + // disable any logging from K8S go-client + // unfortunately restConfig.WarningHandler does not handle auth plugins + klog.SetOutput(io.Discard) + flags := &flag.FlagSet{} + klog.InitFlags(flags) + flags.Set("logtostderr", "false") + config, err := config.NewFromFlags() if err != nil { log.Fatal().Err(err).Msg("failed to parse config flags") diff --git a/cmd/kubent/main_test.go b/cmd/kubent/main_test.go index 4491f97b..4285acdc 100644 --- a/cmd/kubent/main_test.go +++ b/cmd/kubent/main_test.go @@ -117,20 +117,22 @@ func TestMainExitCodes(t *testing.T) { expected int // expected exit code stdout string // expected stdout outFileName string + emptyStderr bool }{ - {"success", []string{clusterFlagDisabled, helm3FlagDisabled}, 0, "", ""}, - {"errorBadFlag", []string{"-c=not-boolean"}, 2, "", ""}, - {"successFound", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, string(expectedJsonOutput), ""}, - {"exitErrorFlagNone", []string{clusterFlagDisabled, helm3FlagDisabled, "-e"}, 0, "", ""}, - {"exitErrorFlagFound", []string{clusterFlagDisabled, helm3FlagDisabled, "-e", "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 200, "", ""}, - {"version short flag set", []string{"-v"}, 0, "", ""}, - {"version long flag set", []string{"--version"}, 0, "", ""}, - {"empty text output", []string{clusterFlagDisabled, helm3FlagDisabled}, 0, "", ""}, - {"empty json output", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled}, 0, "[]\n", ""}, - {"json-file", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, "", filepath.Join(tmpDir, "json-file.out")}, - {"text-file", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, "", filepath.Join(tmpDir, "text-file.out")}, - {"json-stdout", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, string(expectedJsonOutput), "-"}, - {"error-bad-file", []string{clusterFlagDisabled, helm3FlagDisabled}, 1, "", "/this/dir/is/unlikely/to/exist"}, + {"success", []string{clusterFlagDisabled, helm3FlagDisabled}, 0, "", "", false}, + {"errorBadFlag", []string{"-c=not-boolean"}, 2, "", "", false}, + {"successFound", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, string(expectedJsonOutput), "", false}, + {"exitErrorFlagNone", []string{clusterFlagDisabled, helm3FlagDisabled, "-e"}, 0, "", "", false}, + {"exitErrorFlagFound", []string{clusterFlagDisabled, helm3FlagDisabled, "-e", "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 200, "", "", false}, + {"version short flag set", []string{"-v"}, 0, "", "", false}, + {"version long flag set", []string{"--version"}, 0, "", "", false}, + {"empty text output", []string{clusterFlagDisabled, helm3FlagDisabled}, 0, "", "", false}, + {"empty json output", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled}, 0, "[]\n", "", false}, + {"json-file", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, "", filepath.Join(tmpDir, "json-file.out"), false}, + {"text-file", []string{"-o=text", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, "", filepath.Join(tmpDir, "text-file.out"), false}, + {"json-stdout", []string{"-o=json", clusterFlagDisabled, helm3FlagDisabled, "-f=" + filepath.Join(FIXTURES_DIR, "deployment-v1beta1.yaml")}, 0, string(expectedJsonOutput), "-", false}, + {"error-bad-file", []string{clusterFlagDisabled, helm3FlagDisabled}, 1, "", "/this/dir/is/unlikely/to/exist", false}, + {"no-3rdparty-output", []string{clusterFlagDisabled, helm3FlagDisabled, "-l=disabled"}, 0, "", "", true}, } if os.Getenv("TEST_EXIT_CODE") == "1" { @@ -150,11 +152,18 @@ func TestMainExitCodes(t *testing.T) { } base64Args, _ := encodeBase64(tc.args) + var stdout, stderr bytes.Buffer + cmd := exec.Command(os.Args[0], "-test.run=TestMainExitCodes") cmd.Env = append(os.Environ(), "TEST_EXIT_CODE=1", "TEST_ARGS="+base64Args) - out, err := cmd.Output() + cmd.Stdout = &stdout + cmd.Stderr = &stderr + err := cmd.Run() + + outStr := stdout.String() + errStr := stderr.String() if tc.expected == 0 && err != nil { t.Fatalf("expected to succeed with exit code %d, failed with %v", tc.expected, err) @@ -171,16 +180,19 @@ func TestMainExitCodes(t *testing.T) { t.Fatalf("expected to get exit code %d, failed with %v", tc.expected, err) } } - if tc.expected == 0 && err == nil && tc.stdout != string(out) { - t.Fatalf("expected to get stdout as %s, instead got %s", tc.stdout, out) + if tc.expected == 0 && err == nil && tc.stdout != outStr { + t.Fatalf("expected to get stdout as %s, instead got %s", tc.stdout, outStr) } if tc.expected == 0 && err == nil && tc.outFileName != "" && tc.outFileName != "-" { if fs, err := os.Stat(tc.outFileName); err != nil || fs.Size() == 0 { - t.Fatalf("expected non-empty outputdile: %s, got error: %v", tc.outFileName, err) + t.Fatalf("expected non-empty outputfile: %s, got error: %v", tc.outFileName, err) } } + if tc.emptyStderr && errStr != "" { + t.Fatalf("expected empty stderr, got: %s", errStr) + } }) } } diff --git a/go.mod b/go.mod index 34adb5f3..12eabe6d 100644 --- a/go.mod +++ b/go.mod @@ -6,11 +6,12 @@ require ( github.com/ghodss/yaml v1.0.0 github.com/hashicorp/go-version v1.3.0 github.com/open-policy-agent/opa v0.46.1 - github.com/rs/zerolog v1.21.1-0.20210413053206-582f0cf0e39b + github.com/rs/zerolog v1.26.1 github.com/spf13/pflag v1.0.5 helm.sh/helm/v3 v3.10.2 k8s.io/apimachinery v0.25.4 k8s.io/client-go v0.25.4 + k8s.io/klog/v2 v2.70.1 ) require ( @@ -77,7 +78,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.25.4 // indirect k8s.io/apiextensions-apiserver v0.25.2 // indirect - k8s.io/klog/v2 v2.70.1 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect diff --git a/go.sum b/go.sum index f43ba2ed..9104af5c 100644 --- a/go.sum +++ b/go.sum @@ -104,7 +104,6 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -393,9 +392,9 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqn github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -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/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= +github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/rubenv/sql-migrate v1.1.2 h1:9M6oj4e//owVVHYrFISmY9LBRw6gzkCNmD9MV36tZeQ= github.com/rubenv/sql-migrate v1.1.2/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -470,6 +469,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/pkg/collector/kube.go b/pkg/collector/kube.go index f6e102e9..e4b3bc11 100644 --- a/pkg/collector/kube.go +++ b/pkg/collector/kube.go @@ -38,6 +38,7 @@ func newClientRestConfig(kubeconfig string, kubecontext string, inClusterFn func if kubeconfig == "" { if restConfig, err := inClusterFn(); err == nil { restConfig.UserAgent = userAgent + restConfig.WarningHandler = rest.NoWarnings{} return restConfig, nil } } @@ -64,6 +65,7 @@ func newClientRestConfig(kubeconfig string, kubecontext string, inClusterFn func } restConfig.UserAgent = userAgent + restConfig.WarningHandler = rest.NoWarnings{} return restConfig, nil } diff --git a/pkg/collector/kube_test.go b/pkg/collector/kube_test.go index 3a2100f8..26baceac 100644 --- a/pkg/collector/kube_test.go +++ b/pkg/collector/kube_test.go @@ -3,6 +3,7 @@ package collector import ( "os" "path/filepath" + "reflect" "testing" "k8s.io/client-go/rest" @@ -141,6 +142,14 @@ func TestNewClientRestConfigWithContext(t *testing.T) { if config.Host != expectedHost { t.Fatalf("Expected host from context %s to be: %s, got %s instead", expectedContext, expectedHost, config.Host) } + + if config.UserAgent != USER_AGENT { + t.Fatalf("Expected %s UserAgent, instead got: %s", USER_AGENT, config.UserAgent) + } + + if _, ok := config.WarningHandler.(rest.NoWarnings); !ok { + t.Fatalf("Expected NoWarnings warnings handler, instead got: %s", reflect.TypeOf(config.WarningHandler).Name()) + } } func TestNewClientRestConfigContextMissing(t *testing.T) { @@ -165,6 +174,12 @@ func TestNewClientRestConfigInCluster(t *testing.T) { if cfg.Host != expectedHost { t.Fatalf("Expected %s host, instead got: %s", expectedHost, cfg.Host) } + if cfg.UserAgent != USER_AGENT { + t.Fatalf("Expected %s UserAgent, instead got: %s", USER_AGENT, cfg.UserAgent) + } + if _, ok := cfg.WarningHandler.(rest.NoWarnings); !ok { + t.Fatalf("Expected NoWarnings warnings handler, instead got: %s", reflect.TypeOf(cfg.WarningHandler).Name()) + } } type env struct {