From 60c7a353311c65b0b045559873a78ddb510b2b52 Mon Sep 17 00:00:00 2001 From: Adam Janikowski <12255597+ajanikow@users.noreply.github.com> Date: Fri, 4 Nov 2022 17:39:40 +0100 Subject: [PATCH] [Debug] Allow to send package to stdout (#1173) --- CHANGELOG.md | 1 + cmd/debug.go | 28 +++-- pkg/debug_package/cli/cli.go | 40 +++++++ pkg/debug_package/generator.go | 22 +++- .../generators/kubernetes/events.go | 79 +++++++------- .../generators/kubernetes/pods.go | 79 +++++++------- .../generators/kubernetes/secrets.go | 102 ++++++++---------- pkg/debug_package/out.go | 2 +- pkg/debug_package/shared/file.go | 24 ++--- 9 files changed, 213 insertions(+), 164 deletions(-) create mode 100644 pkg/debug_package/cli/cli.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 66042d650..642d94489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - (Feature) Create Internal Actions and move RebalancerGenerator - (Dependencies) Bump K8S Dependencies to 1.22.15 - (Bugfix) Unlock broken inspectors +- (Debug) Allow to send package to stdout ## [1.2.20](https://github.com/arangodb/kube-arangodb/tree/1.2.20) (2022-10-25) - (Feature) Add action progress diff --git a/cmd/debug.go b/cmd/debug.go index 7f6a73930..394ba0fca 100644 --- a/cmd/debug.go +++ b/cmd/debug.go @@ -32,6 +32,10 @@ import ( func init() { cmdMain.AddCommand(debugPackage) + f := debugPackage.Flags() + + f.StringVarP(&debugPackageInput.Output, "output", "o", "out.tar.gz", "Output of the result gz file. If set to `-` then stdout is used") + debug_package.InitCommand(debugPackage) } @@ -41,13 +45,23 @@ var debugPackage = &cobra.Command{ RunE: debugPackageFunc, } +var debugPackageInput struct { + Output string +} + func debugPackageFunc(cmd *cobra.Command, _ []string) error { - f, err := os.OpenFile("./out.tar.gz", os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0644) - if err != nil { - return err + out := os.Stdout + + if debugPackageInput.Output != "-" { + f, err := os.OpenFile("./out.tar.gz", os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + return err + } + + out = f } - gw := gzip.NewWriter(f) + gw := gzip.NewWriter(out) if err := debug_package.GenerateD(cmd, gw); err != nil { return err @@ -57,8 +71,10 @@ func debugPackageFunc(cmd *cobra.Command, _ []string) error { return err } - if err := f.Close(); err != nil { - return err + if debugPackageInput.Output != "-" { + if err := out.Close(); err != nil { + return err + } } return nil diff --git a/pkg/debug_package/cli/cli.go b/pkg/debug_package/cli/cli.go new file mode 100644 index 000000000..0f487d171 --- /dev/null +++ b/pkg/debug_package/cli/cli.go @@ -0,0 +1,40 @@ +// +// DISCLAIMER +// +// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package cli + +import "github.com/spf13/cobra" + +func Register(cmd *cobra.Command) { + f := cmd.Flags() + f.StringVar(&input.Namespace, "namespace", "default", "Kubernetes namespace") + f.BoolVar(&input.HideSensitiveData, "hide-sensitive-data", true, "Hide sensitive data") +} + +var input Input + +func GetInput() Input { + return input +} + +type Input struct { + Namespace string + HideSensitiveData bool +} diff --git a/pkg/debug_package/generator.go b/pkg/debug_package/generator.go index 3b7cfdbe1..2d49c6be1 100644 --- a/pkg/debug_package/generator.go +++ b/pkg/debug_package/generator.go @@ -23,11 +23,13 @@ package debug_package import ( "archive/tar" "bytes" + "fmt" "io" "time" "github.com/spf13/cobra" + "github.com/arangodb/kube-arangodb/pkg/debug_package/cli" "github.com/arangodb/kube-arangodb/pkg/debug_package/generators/kubernetes" "github.com/arangodb/kube-arangodb/pkg/debug_package/shared" "github.com/arangodb/kube-arangodb/pkg/util/errors" @@ -40,8 +42,14 @@ var rootFactories = []shared.Factory{ } func InitCommand(cmd *cobra.Command) { - for _, f := range rootFactories { - f.Init(cmd) + cli.Register(cmd) + + f := cmd.Flags() + + for _, factory := range rootFactories { + n := fmt.Sprintf("generator.%s", factory.Name()) + + f.Bool(n, factory.Enabled(), fmt.Sprintf("Define if generator %s is enabled", factory.Name())) } } @@ -97,8 +105,16 @@ func Generate(cmd *cobra.Command, out io.Writer, factories ...shared.Factory) er }() for _, f := range factories { + ok, _ := cmd.Flags().GetBool(fmt.Sprintf("generator.%s", f.Name())) + + if !ok { + log.Info().Msgf("Factory %s disabled", f.Name()) + continue + } + log.Info().Msgf("Fetching factory %s", f.Name()) - if err := f.Generate(cmd, log, files); err != nil { + + if err := f.Generate(log, files); err != nil { factoryErrors[f.Name()] = err } } diff --git a/pkg/debug_package/generators/kubernetes/events.go b/pkg/debug_package/generators/kubernetes/events.go index f6080e6d0..d0e618d87 100644 --- a/pkg/debug_package/generators/kubernetes/events.go +++ b/pkg/debug_package/generators/kubernetes/events.go @@ -24,61 +24,56 @@ import ( "context" "github.com/rs/zerolog" - "github.com/spf13/cobra" eventsv1 "k8s.io/api/events/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "github.com/arangodb/kube-arangodb/pkg/debug_package/cli" "github.com/arangodb/kube-arangodb/pkg/debug_package/shared" "github.com/arangodb/kube-arangodb/pkg/util/errors" "github.com/arangodb/kube-arangodb/pkg/util/kclient" ) func Events() shared.Factory { - return shared.NewFactory("kubernetes-events", func(cmd *cobra.Command) { - f := cmd.Flags() - if f.Lookup("namespace") == nil { - f.String("namespace", "default", "Kubernetes namespace") - } - }, func(cmd *cobra.Command, logger zerolog.Logger, files chan<- shared.File) error { - k, ok := kclient.GetDefaultFactory().Client() - if !ok { - return errors.Newf("Client is not initialised") - } + return shared.NewFactory("kubernetes-events", true, events) +} - ns, _ := cmd.Flags().GetString("namespace") +func events(logger zerolog.Logger, files chan<- shared.File) error { + k, ok := kclient.GetDefaultFactory().Client() + if !ok { + return errors.Newf("Client is not initialised") + } - events := map[types.UID]*eventsv1.Event{} - next := "" - for { - r, err := k.Kubernetes().EventsV1().Events(ns).List(context.Background(), meta.ListOptions{ - Continue: next, - }) - - if err != nil { - return err - } - - for _, e := range r.Items { - events[e.UID] = e.DeepCopy() - } - - next = r.Continue - if next == "" { - break - } - } - - files <- shared.NewJSONFile("kubernetes/events.json", func() (interface{}, error) { - q := make([]*eventsv1.Event, 0, len(events)) - - for _, e := range events { - q = append(q, e) - } - - return q, nil + events := map[types.UID]*eventsv1.Event{} + next := "" + for { + r, err := k.Kubernetes().EventsV1().Events(cli.GetInput().Namespace).List(context.Background(), meta.ListOptions{ + Continue: next, }) - return nil + if err != nil { + return err + } + + for _, e := range r.Items { + events[e.UID] = e.DeepCopy() + } + + next = r.Continue + if next == "" { + break + } + } + + files <- shared.NewJSONFile("kubernetes/events.json", func() (interface{}, error) { + q := make([]*eventsv1.Event, 0, len(events)) + + for _, e := range events { + q = append(q, e) + } + + return q, nil }) + + return nil } diff --git a/pkg/debug_package/generators/kubernetes/pods.go b/pkg/debug_package/generators/kubernetes/pods.go index 6427246d9..189325e28 100644 --- a/pkg/debug_package/generators/kubernetes/pods.go +++ b/pkg/debug_package/generators/kubernetes/pods.go @@ -24,61 +24,56 @@ import ( "context" "github.com/rs/zerolog" - "github.com/spf13/cobra" core "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "github.com/arangodb/kube-arangodb/pkg/debug_package/cli" "github.com/arangodb/kube-arangodb/pkg/debug_package/shared" "github.com/arangodb/kube-arangodb/pkg/util/errors" "github.com/arangodb/kube-arangodb/pkg/util/kclient" ) func Pods() shared.Factory { - return shared.NewFactory("kubernetes-pods", func(cmd *cobra.Command) { - f := cmd.Flags() - if f.Lookup("namespace") == nil { - f.String("namespace", "default", "Kubernetes namespace") - } - }, func(cmd *cobra.Command, logger zerolog.Logger, files chan<- shared.File) error { - k, ok := kclient.GetDefaultFactory().Client() - if !ok { - return errors.Newf("Client is not initialised") - } + return shared.NewFactory("kubernetes-pods", true, pods) +} - ns, _ := cmd.Flags().GetString("namespace") +func pods(logger zerolog.Logger, files chan<- shared.File) error { + k, ok := kclient.GetDefaultFactory().Client() + if !ok { + return errors.Newf("Client is not initialised") + } - pods := map[types.UID]*core.Pod{} - next := "" - for { - r, err := k.Kubernetes().CoreV1().Pods(ns).List(context.Background(), meta.ListOptions{ - Continue: next, - }) - - if err != nil { - return err - } - - for _, e := range r.Items { - pods[e.UID] = e.DeepCopy() - } - - next = r.Continue - if next == "" { - break - } - } - - files <- shared.NewJSONFile("kubernetes/pods.json", func() (interface{}, error) { - q := make([]*core.Pod, 0, len(pods)) - - for _, e := range pods { - q = append(q, e) - } - - return q, nil + pods := map[types.UID]*core.Pod{} + next := "" + for { + r, err := k.Kubernetes().CoreV1().Pods(cli.GetInput().Namespace).List(context.Background(), meta.ListOptions{ + Continue: next, }) - return nil + if err != nil { + return err + } + + for _, e := range r.Items { + pods[e.UID] = e.DeepCopy() + } + + next = r.Continue + if next == "" { + break + } + } + + files <- shared.NewJSONFile("kubernetes/pods.json", func() (interface{}, error) { + q := make([]*core.Pod, 0, len(pods)) + + for _, e := range pods { + q = append(q, e) + } + + return q, nil }) + + return nil } diff --git a/pkg/debug_package/generators/kubernetes/secrets.go b/pkg/debug_package/generators/kubernetes/secrets.go index 576c8c62b..2d7df07aa 100644 --- a/pkg/debug_package/generators/kubernetes/secrets.go +++ b/pkg/debug_package/generators/kubernetes/secrets.go @@ -26,75 +26,65 @@ import ( "fmt" "github.com/rs/zerolog" - "github.com/spf13/cobra" core "k8s.io/api/core/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "github.com/arangodb/kube-arangodb/pkg/debug_package/cli" "github.com/arangodb/kube-arangodb/pkg/debug_package/shared" "github.com/arangodb/kube-arangodb/pkg/util/errors" "github.com/arangodb/kube-arangodb/pkg/util/kclient" ) func Secrets() shared.Factory { - return shared.NewFactory("kubernetes-secrets", func(cmd *cobra.Command) { - f := cmd.Flags() - if f.Lookup("namespace") == nil { - f.String("namespace", "default", "Kubernetes namespace") - } - if f.Lookup("hide-sensitive-data") == nil { - f.Bool("hide-sensitive-data", true, "Hide sensitive data") - } - }, func(cmd *cobra.Command, logger zerolog.Logger, files chan<- shared.File) error { - k, ok := kclient.GetDefaultFactory().Client() - if !ok { - return errors.Newf("Client is not initialised") - } + return shared.NewFactory("kubernetes-secrets", true, secrets) +} - ns, _ := cmd.Flags().GetString("namespace") +func secrets(logger zerolog.Logger, files chan<- shared.File) error { + k, ok := kclient.GetDefaultFactory().Client() + if !ok { + return errors.Newf("Client is not initialised") + } - secrets := map[types.UID]*core.Secret{} - next := "" - for { - r, err := k.Kubernetes().CoreV1().Secrets(ns).List(context.Background(), meta.ListOptions{ - Continue: next, - }) - - if err != nil { - return err - } - - sensitive, _ := cmd.Flags().GetBool("hide-sensitive-data") - - for _, e := range r.Items { - hashed := make(map[string][]byte, len(e.Data)) - for k, v := range e.Data { - if sensitive { - hashed[k] = []byte(fmt.Sprintf("%02x", sha256.Sum256(v))) - } else { - hashed[k] = v - } - } - secrets[e.UID] = e.DeepCopy() - secrets[e.UID].Data = hashed - } - - next = r.Continue - if next == "" { - break - } - } - - files <- shared.NewJSONFile("kubernetes/secrets.json", func() (interface{}, error) { - q := make([]*core.Secret, 0, len(secrets)) - - for _, e := range secrets { - q = append(q, e) - } - - return q, nil + secrets := map[types.UID]*core.Secret{} + next := "" + for { + r, err := k.Kubernetes().CoreV1().Secrets(cli.GetInput().Namespace).List(context.Background(), meta.ListOptions{ + Continue: next, }) - return nil + if err != nil { + return err + } + + for _, e := range r.Items { + hashed := make(map[string][]byte, len(e.Data)) + for k, v := range e.Data { + if cli.GetInput().HideSensitiveData { + hashed[k] = []byte(fmt.Sprintf("%02x", sha256.Sum256(v))) + } else { + hashed[k] = v + } + } + secrets[e.UID] = e.DeepCopy() + secrets[e.UID].Data = hashed + } + + next = r.Continue + if next == "" { + break + } + } + + files <- shared.NewJSONFile("kubernetes/secrets.json", func() (interface{}, error) { + q := make([]*core.Secret, 0, len(secrets)) + + for _, e := range secrets { + q = append(q, e) + } + + return q, nil }) + + return nil } diff --git a/pkg/debug_package/out.go b/pkg/debug_package/out.go index e9966a898..3e2a48d47 100644 --- a/pkg/debug_package/out.go +++ b/pkg/debug_package/out.go @@ -29,5 +29,5 @@ import ( ) func NewLogger(out io.Writer) zerolog.Logger { - return zerolog.New(zerolog.ConsoleWriter{Out: io.MultiWriter(out, os.Stdout), TimeFormat: time.RFC3339}).With().Timestamp().Logger() + return zerolog.New(zerolog.ConsoleWriter{Out: io.MultiWriter(out, os.Stderr), TimeFormat: time.RFC3339}).With().Timestamp().Logger() } diff --git a/pkg/debug_package/shared/file.go b/pkg/debug_package/shared/file.go index cefcc25f6..238828bb5 100644 --- a/pkg/debug_package/shared/file.go +++ b/pkg/debug_package/shared/file.go @@ -22,11 +22,10 @@ package shared import ( "github.com/rs/zerolog" - "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/json" ) -type GenFunc func(cmd *cobra.Command, logger zerolog.Logger, files chan<- File) error +type GenFunc func(logger zerolog.Logger, files chan<- File) error type File interface { Path() string @@ -66,35 +65,32 @@ func (f file) Write() ([]byte, error) { type Factory interface { Name() string - Generate(cmd *cobra.Command, logger zerolog.Logger, files chan<- File) error - - Init(command *cobra.Command) + Generate(logger zerolog.Logger, files chan<- File) error + Enabled() bool } -func NewFactory(name string, cmd func(cmd *cobra.Command), gen GenFunc) Factory { +func NewFactory(name string, enabled bool, gen GenFunc) Factory { return factory{ name: name, + enabled: enabled, generate: gen, - cmd: cmd, } } type factory struct { name string + enabled bool generate GenFunc - cmd func(cmd *cobra.Command) } -func (f factory) Init(command *cobra.Command) { - if c := f.cmd; c != nil { - c(command) - } +func (f factory) Enabled() bool { + return f.enabled } func (f factory) Name() string { return f.name } -func (f factory) Generate(cmd *cobra.Command, logger zerolog.Logger, files chan<- File) error { - return f.generate(cmd, logger, files) +func (f factory) Generate(logger zerolog.Logger, files chan<- File) error { + return f.generate(logger, files) }