cyberark / kubeletctl

A client for kubelet
Apache License 2.0
713 stars 81 forks source link

kubeletctl panics when no arguments are provided to some commands #5

Closed jimen0 closed 4 years ago

jimen0 commented 4 years ago

kubeletctl commands that require arguments cause a panicif no arguments are provided. I confirmed this behaviour with this release.

$ ./kubeletctl --http --server REDACTED --port 10255 debug
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
kubeletctl/cmd/proxy/debug.glob..func1(0x15708a0, 0xc00034e320, 0x0, 0x5)
    /home/ubuntu/test/kubeletctl/cmd/proxy/debug/debug.go:89 +0x1e1
github.com/spf13/cobra.(*Command).execute(0x15708a0, 0xc00034e2d0, 0x5, 0x5, 0x15708a0, 0xc00034e2d0)
    /home/ubuntu/test/kubeletctl/vendor/github.com/spf13/cobra/command.go:842 +0x29d
github.com/spf13/cobra.(*Command).ExecuteC(0x156dea0, 0x443cba, 0x151f1a0, 0xc000000180)
    /home/ubuntu/test/kubeletctl/vendor/github.com/spf13/cobra/command.go:943 +0x317
github.com/spf13/cobra.(*Command).Execute(...)
    /home/ubuntu/test/kubeletctl/vendor/github.com/spf13/cobra/command.go:883
kubeletctl/cmd.Execute()
    /home/ubuntu/test/kubeletctl/cmd/root.go:66 +0x31
main.main()
    /home/ubuntu/test/kubeletctl/main.go:20 +0x20

Panic comes from the following snippet:

var inputArgs string
if args == nil {
    fmt.Println("[*] No debug profile was specified")
    os.Exit(1)
} else {
    inputArgs = args[0]
}

The error comes from checking if the arguments slice is nil instead of checking the number of arguments (length of a nil slice is 0 too, see the playground). If no arguments are provided, cobra passes an empty slice as argument, not nil.

I confirmed this behaviour in the debug and exec commands, but it might be present in more of them.

I built this small repro so you can check cobra's behaviour when no arguments are provided:

package main

import (
    "fmt"

    "github.com/spf13/cobra"
)

func main() {
    cmdPrint := &cobra.Command{
        Use: "print [str]",
        Run: func(_ *cobra.Command, args []string) {
            fmt.Printf("args: %#+v\n", args)
        },
    }

    rootCmd := &cobra.Command{Use: "app"}
    rootCmd.AddCommand(cmdPrint)
    rootCmd.Execute()
}
:/tmp/example$ go run main.go print
args: []string{}
:/tmp/example$ go run main.go print foo
args: []string{"foo"}

Regards, Miguel

g3rzi commented 4 years ago

Thanks !

I will fix it and update, but you can still use the debug command meanwhile.

If you will run kubeletctl debug -h you will see the usage:

Usage:
  kubeletctl debug <pprof_profiles> [flags]
  kubeletctl debug [command]

Example for pprof profiles:

  Examples:
    /debug/pprof/                    // to view all available profiles
    /debug/pprof/profile
    /debug/pprof/profile?seconds=30 // look at 30-second CPU profile
    /debug/pprof/symbol
    /debug/pprof/cmdline
    /debug/pprof/trace
    /debug/pprof/trace?seconds=5    // collect 5-second execution trace
    /debug/pprof/block              // look at the goroutine blocking profile
    /debug/pprof/mutex              // look at the holderse of contended mutexes
    /debug/pprof/heap               // look at the heap profile

  Profile Descriptions:
    "allocs":       A sampling of all past memory allocations.
    "block":        Stack traces that led to blocking on synchronization primitives.
    "cmdline":      The command line invocation of the current program.
    "goroutine":    Stack traces of all current goroutines.
    "heap":         A sampling of memory allocations of live objects.
                    You can specify the gc GET parameter to run GC before taking the heap sample.
    "mutex":        Stack traces of holders of contended mutexes.
    "profile":      CPU profile. You can specify the duration in the seconds GET parameter. After you get the profile file,
                    use the go tool pprof command to investigate the profile.
    "threadcreate": Stack traces that led to the creation of new OS threads.
    "trace":        A trace of execution of the current program. You can specify the duration in the seconds GET parameter.
                    After you get the trace file, use the go tool trace command to investigate the trace.

So a valid debug command will be:

C:\>kubeletctl_windows_amd64.exe -s <node_ip> debug symbol
num_symbols: 1

Or

C:\>kubeletctl_windows_amd64.exe -s <node_ip> debug block
<REDACTED>
g3rzi commented 4 years ago

@jimen0 thank you for reporting this issue :) I currently fixed it for debug and exec.
It might appear also in other commands like you said, if I will see it in other commands I will fix them too.

I tested it for the two commands you said and now it is fixed in version v1.5. If you still have issues, let me know.