Я пишу плагин 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
плагинов, но яхотите предложить пользователю ввести данные - есть ли простой способ сделать это?