Внутри плагин kubectl, подскажите для ввода? - PullRequest
0 голосов
/ 27 июня 2019

Я пишу плагин kubectl для аутентификации пользователей, и я хотел бы попросить пользователя ввести пароль после его запуска.Из того, что я понимаю, довольно просто получить информацию от STDIN, но я изо всех сил пытаюсь увидеть сообщения, записанные в STDOUT.В настоящее время мой код выглядит следующим образом:

В cmd / kubectl-myauth.go:

// This is mostly boilerplate, but it's needed for the MRE
// https://stackoverflow.com/help/minimal-reproducible-example
package myauth
import (...)
func main() {
    pflag.CommandLine = pflag.NewFlagSet("kubectl-myauth", pflag.ExitOnError)
    root := cmd.NewCmdAuthOp(genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr})
    if err := root.Execute(); err != nil {
        os.Exit(1)
    }
}

В pkg / cmd / auth.go:

package cmd
...
type AuthOpOptions struct {
    configFlags *genericclioptions.ConfigFlags
    resultingContext *api.Context
    rawConfig       api.Config
    args            []string
    ...
    genericclioptions.IOStreams
}
func NewAuthOpOptions(streams genericclioptions.IOStreams) *AuthOpOptions {
    return &AuthOpOptions{
        configFlags: genericclioptions.NewConfigFlags(true),
        IOStreams: streams,
    }
}
func NewCmdAuthOp(streams genericclioptions.IOStreams) *cobra.Command {
    o := NewAuthOpOptions(streams)
    cmd := &cobra.Command{
        RunE: func(c *cobra.Command, args []string) error {
            return o.Run()
        },
    }
    return cmd
}
func (o *AuthOpOptions) Run() error {
    pass, err := getPassword(o)
    if err != nil {
        return err
    }
    // Do Auth Stuff
    // Eventually print an ExecCredential to STDOUT
    return nil
}
func getPassword(o *AuthOpOptions) (string, error) {
    var reader *bufio.Reader
    reader = nil
    pass := ""
    for pass == "" {
        // THIS IS AN IMPORTANT LINE [1]
        fmt.Fprintf(o.IOStreams.Out, "Password with which to authenticate:\n")
        // THE REST OF THIS IS STILL IMPORTANT, BUT LESS SO [2]
        if reader == nil {
            // The first time through, initialize the reader
            reader = bufio.NewReader(o.IOStreams.In)
        }
        pass, err := reader.ReadString('\n')
        if err != nil {
            return nil, err
        }
        pass = strings.Trim(pass, "\r\n")
        if pass == "" {
            // ALSO THIS LINE IS IMPORTANT [3]
            fmt.Fprintf(o.IOStreams.Out, `Read password was empty string.
Please input a valid password.
`)
        }
    }
    return pass, nil
}

Thisработает так, как я ожидаю при запуске вне контекста kubectl, а именно: он печатает строку, запрашивает ввод и продолжает работу.Однако из контекста kubectl я полагаю, что печать между первыми двумя комментариями со всеми заглавными буквами ([1] и [2]) проглатывается kubectl прослушиванием STDOUT.Я могу обойти это, печатая в STDERR, но это кажется ... неправильным.Есть ли способ, которым я могу обойти kubectl потребление STDOUT для связи с пользователем?

TL; DR: kubectl, кажется, поглощает все STDOUT для kubectl плагинов, но яхотите предложить пользователю ввести данные - есть ли простой способ сделать это?

...