From 3fb7f42ff7237d12dce0bb5d54209b2ad96c3ad9 Mon Sep 17 00:00:00 2001 From: Aaron Alpar <55999015+aaron-kasten@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:35:35 -0800 Subject: [PATCH] feat: Allow quiet operation in KanX; fixup logging. (#3343) Signed-off-by: Aaron Alpar --- pkg/kando/kando.go | 20 ++++++++--- pkg/kando/process_client.go | 10 ++++++ pkg/kando/process_client_create.go | 4 +++ pkg/kando/process_client_execute.go | 17 +++++---- pkg/kando/process_client_get.go | 8 +++-- pkg/kando/process_client_signal.go | 4 +++ pkg/kopia/command/common.go | 12 +------ pkg/kopia/command/server.go | 2 +- .../maintenance/get_maintenance_owner.go | 35 +++++++++++++++++++ 9 files changed, 86 insertions(+), 26 deletions(-) diff --git a/pkg/kando/kando.go b/pkg/kando/kando.go index 755085db5c..5e01863916 100644 --- a/pkg/kando/kando.go +++ b/pkg/kando/kando.go @@ -15,11 +15,13 @@ package kando import ( + "fmt" "os" "github.com/kanisterio/errkit" "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "google.golang.org/grpc/grpclog" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/version" @@ -46,8 +48,13 @@ func newRootCommand() *cobra.Command { } rootCmd.PersistentFlags().StringVarP(&logLevel, "verbosity", "v", logrus.WarnLevel.String(), "Log level (debug, info, warn, error, fatal, panic)") - rootCmd.PersistentPreRunE = func(*cobra.Command, []string) error { - return setLogLevel(logLevel) + rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { + err := setLogLevel(logLevel) + if err != nil { + return err + } + grpclog.SetLoggerV2(grpclogLogger(cmd)) + return nil } rootCmd.AddCommand(newLocationCommand()) @@ -59,10 +66,13 @@ func newRootCommand() *cobra.Command { } func setLogLevel(v string) error { - l, err := logrus.ParseLevel(v) + lgl, err := logrus.ParseLevel(v) if err != nil { - return errkit.Wrap(err, "Invalid log level: "+v) + return errkit.Wrap(err, fmt.Sprintf("Invalid log level: %s", v)) } - logrus.SetLevel(l) + // set application logger log level. (kanister/log/log.go) + log.SetLevel(log.Level(lgl)) + // set "std" logrus logger. GRPC uses this (logrus/exported) + logrus.SetLevel(lgl) return nil } diff --git a/pkg/kando/process_client.go b/pkg/kando/process_client.go index 2b9ac46d6e..f5b6ac66f3 100644 --- a/pkg/kando/process_client.go +++ b/pkg/kando/process_client.go @@ -31,6 +31,7 @@ import ( const ( processSignalProxyFlagName = "signal-proxy" processAsJSONFlagName = "as-json" + processAsQuietFlagName = "quiet" ) func newProcessClientCommand() *cobra.Command { @@ -45,6 +46,7 @@ func newProcessClientCommand() *cobra.Command { cmd.AddCommand(newProcessClientSignalCommand()) cmd.AddCommand(newProcessClientOutputCommand()) cmd.PersistentFlags().BoolP(processAsJSONFlagName, "j", false, "Display output as json") + cmd.PersistentFlags().BoolP(processAsQuietFlagName, "q", false, "Quiet process information output") return cmd } @@ -56,6 +58,14 @@ func processAsJSONFlagValue(cmd *cobra.Command) bool { return b } +func processAsQuietFlagValue(cmd *cobra.Command) bool { + b, err := cmd.Flags().GetBool(processAsQuietFlagName) + if err != nil { + panic(err.Error()) + } + return b +} + func proxySetup(ctx context.Context, addr string, pid int64) { log.Info().WithContext(ctx).Print(fmt.Sprintf("signal proxy is running for process %d", pid)) signalTermChan := make(chan os.Signal, 1) diff --git a/pkg/kando/process_client_create.go b/pkg/kando/process_client_create.go index 62d2a71296..ad229dfe4a 100644 --- a/pkg/kando/process_client_create.go +++ b/pkg/kando/process_client_create.go @@ -44,11 +44,15 @@ func runProcessClientCreateWithOutput(out io.Writer, cmd *cobra.Command, args [] return err } asJSON := processAsJSONFlagValue(cmd) + asQuiet := processAsQuietFlagValue(cmd) cmd.SilenceUsage = true p, err := kanx.CreateProcess(cmd.Context(), addr, args[0], args[1:]) if err != nil { return err } + if asQuiet { + return nil + } if asJSON { buf, err := protojson.Marshal(p) if err != nil { diff --git a/pkg/kando/process_client_execute.go b/pkg/kando/process_client_execute.go index de2fc87b25..10cf06da72 100644 --- a/pkg/kando/process_client_execute.go +++ b/pkg/kando/process_client_execute.go @@ -51,6 +51,7 @@ func runProcessClientExecuteWithOutput(stdout, stderr io.Writer, cmd *cobra.Comm return err } asJSON := processAsJSONFlagValue(cmd) + asQuiet := processAsQuietFlagValue(cmd) cmd.SilenceUsage = true ctx, canfn := context.WithCancel(cmd.Context()) defer canfn() @@ -58,14 +59,16 @@ func runProcessClientExecuteWithOutput(stdout, stderr io.Writer, cmd *cobra.Comm if err != nil { return err } - if asJSON { - buf, err := protojson.Marshal(p) - if err != nil { - return err + if !asQuiet { + if asJSON { + buf, err := protojson.Marshal(p) + if err != nil { + return err + } + fmt.Fprintln(stdout, string(buf)) + } else { + fmt.Fprintln(stdout, "Process: ", p) } - fmt.Fprintln(stdout, string(buf)) - } else { - fmt.Fprintln(stdout, "Process: ", p) } pid := p.Pid diff --git a/pkg/kando/process_client_get.go b/pkg/kando/process_client_get.go index 7ea8e1bf2a..f365d07514 100644 --- a/pkg/kando/process_client_get.go +++ b/pkg/kando/process_client_get.go @@ -40,7 +40,7 @@ func runProcessClientGet(cmd *cobra.Command, args []string) error { } func runProcessClientGetWithOutput(out io.Writer, cmd *cobra.Command, args []string) error { - pid, err := strconv.Atoi(args[0]) + pid, err := strconv.ParseInt(args[0], 0, 64) if err != nil { return err } @@ -48,12 +48,16 @@ func runProcessClientGetWithOutput(out io.Writer, cmd *cobra.Command, args []str if err != nil { return err } + asQuiet := processAsQuietFlagValue(cmd) asJSON := processAsJSONFlagValue(cmd) cmd.SilenceUsage = true - p, err := kanx.GetProcess(cmd.Context(), addr, int64(pid)) + p, err := kanx.GetProcess(cmd.Context(), addr, pid) if err != nil { return err } + if asQuiet { + return nil + } if asJSON { buf, err := protojson.Marshal(p) if err != nil { diff --git a/pkg/kando/process_client_signal.go b/pkg/kando/process_client_signal.go index b887851bba..4b5af563f2 100644 --- a/pkg/kando/process_client_signal.go +++ b/pkg/kando/process_client_signal.go @@ -52,12 +52,16 @@ func runProcessClientSignalWithOutput(out io.Writer, cmd *cobra.Command, args [] if err != nil { return err } + asQuiet := processAsQuietFlagValue(cmd) asJSON := processAsJSONFlagValue(cmd) cmd.SilenceUsage = true p, err := kanx.SignalProcess(cmd.Context(), addr, pid, signal) if err != nil { return err } + if asQuiet { + return nil + } if asJSON { buf, err := protojson.Marshal(p) if err != nil { diff --git a/pkg/kopia/command/common.go b/pkg/kopia/command/common.go index 8e7557db69..44fe5b57a3 100644 --- a/pkg/kopia/command/common.go +++ b/pkg/kopia/command/common.go @@ -64,19 +64,9 @@ func bashCommand(args logsafe.Cmd) []string { return []string{"bash", "-o", "errexit", "-c", args.PlainText()} } -func bashCommandAsLogSafe(args logsafe.Cmd) logsafe.Cmd { - log.Info().Print("Kopia Command", field.M{"Command": args.String()}) - return logsafe.NewLoggable("bash", "-o", "errexit", "-c").Combine(args) -} - -func kanxCommand(args logsafe.Cmd) []string { - log.Info().Print("Kopia Command", field.M{"Command": args.String()}) - return append([]string{"kando", "process", "client", "execute", "--signal-proxy", "--as-json", "--"}, args.StringSliceCMD()...) -} - func MakeKanxCommand(args []string) []string { log.Info().Print("KanX Command", field.M{"Command": args}) - return append([]string{"kando", "process", "client", "execute", "--signal-proxy", "--as-json", "--"}, args...) + return append([]string{"kando", "process", "client", "execute", "--signal-proxy", "--quiet", "--"}, args...) } func stringSliceCommand(args logsafe.Cmd) []string { diff --git a/pkg/kopia/command/server.go b/pkg/kopia/command/server.go index 1bcdf65b95..de40d26974 100644 --- a/pkg/kopia/command/server.go +++ b/pkg/kopia/command/server.go @@ -86,7 +86,7 @@ func ServerStart(cmdArgs ServerStartCommandArgs) []string { // ServerStartKanx returns the kopia command for starting the Kopia API Server func ServerStartKanx(cmdArgs ServerStartCommandArgs) []string { - return kanxCommand(bashCommandAsLogSafe(commonCommand(cmdArgs))) + return MakeKanxCommand(ServerStart(cmdArgs)) } type ServerRefreshCommandArgs struct { diff --git a/pkg/kopia/maintenance/get_maintenance_owner.go b/pkg/kopia/maintenance/get_maintenance_owner.go index c9d5fe551c..dd0d788bff 100644 --- a/pkg/kopia/maintenance/get_maintenance_owner.go +++ b/pkg/kopia/maintenance/get_maintenance_owner.go @@ -72,6 +72,41 @@ func GetMaintenanceOwnerForConnectedRepository( return parseOwner(stdout.Bytes()) } +// GetMaintenanceOwnerForConnectedRepositoryKanx executes maintenance info command, +// and returns maintenance owner. +func GetMaintenanceOwnerForConnectedRepositoryKanx( + ctx context.Context, + podController kube.PodController, + configFilePath, + logDirectory string, +) (string, error) { + pod := podController.Pod() + container := pod.Spec.Containers[0].Name + commandExecutor, err := podController.GetCommandExecutor() + if err != nil { + return "", err + } + + args := command.MaintenanceInfoCommandArgs{ + CommandArgs: &command.CommandArgs{ + ConfigFilePath: configFilePath, + LogDirectory: logDirectory, + }, + GetJSONOutput: true, + } + cmd := command.MaintenanceInfo(args) + + var stdout, stderr bytes.Buffer + err = commandExecutor.Exec(ctx, command.MakeKanxCommand(cmd), nil, &stdout, &stderr) + format.LogWithCtx(ctx, pod.Name, container, stdout.String()) + format.LogWithCtx(ctx, pod.Name, container, stderr.String()) + if err != nil { + return "", err + } + + return parseOwner(stdout.Bytes()) +} + func parseOwner(output []byte) (string, error) { maintInfo := kopiacli.MaintenanceInfo{} if err := json.Unmarshal(output, &maintInfo); err != nil {