diff --git a/cmd/login_cloud.go b/cmd/login_cloud.go index 453743ad5a1..f440a81cd56 100644 --- a/cmd/login_cloud.go +++ b/cmd/login_cloud.go @@ -22,10 +22,13 @@ package cmd import ( "os" + "syscall" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/afero" "github.com/spf13/cobra" + "golang.org/x/crypto/ssh/terminal" "gopkg.in/guregu/null.v3" "github.com/loadimpact/k6/lib/consts" @@ -51,6 +54,8 @@ This will set the default token used when just "k6 run -o cloud" is passed.`, k6 login cloud`[1:], Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { + // TODO: don't use a global... or maybe change the logger? + logger := logrus.StandardLogger() fs := afero.NewOsFs() k6Conf, err := getConsolidatedConfig(fs, Config{}, nil) @@ -89,6 +94,9 @@ This will set the default token used when just "k6 run -o cloud" is passed.`, }, }, } + if !terminal.IsTerminal(int(syscall.Stdin)) { // nolint: unconvert + logger.Warn("Stdin is not a terminal, falling back to plain text input") + } vals, err := form.Run(os.Stdin, stdout) if err != nil { return err diff --git a/cmd/login_influxdb.go b/cmd/login_influxdb.go index 44de72c141c..602ccb41ee6 100644 --- a/cmd/login_influxdb.go +++ b/cmd/login_influxdb.go @@ -22,11 +22,14 @@ package cmd import ( "os" + "syscall" "time" "github.com/mitchellh/mapstructure" + "github.com/sirupsen/logrus" "github.com/spf13/afero" "github.com/spf13/cobra" + "golang.org/x/crypto/ssh/terminal" "github.com/loadimpact/k6/lib/types" "github.com/loadimpact/k6/stats/influxdb" @@ -42,6 +45,8 @@ var loginInfluxDBCommand = &cobra.Command{ This will set the default server used when just "-o influxdb" is passed.`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + // TODO: don't use a global... or maybe change the logger? + logger := logrus.StandardLogger() fs := afero.NewOsFs() config, configPath, err := readDiskConfig(fs) if err != nil { @@ -80,6 +85,9 @@ This will set the default server used when just "-o influxdb" is passed.`, }, }, } + if !terminal.IsTerminal(int(syscall.Stdin)) { // nolint: unconvert + logger.Warn("Stdin is not a terminal, falling back to plain text input") + } vals, err := form.Run(os.Stdin, stdout) if err != nil { return err diff --git a/cmd/ui.go b/cmd/ui.go index 70b272a16a4..93a59a71913 100644 --- a/cmd/ui.go +++ b/cmd/ui.go @@ -46,7 +46,8 @@ const ( maxLeftLength = 30 // Amount of padding in chars between rendered progress // bar text and right-side terminal window edge. - termPadding = 1 + termPadding = 1 + defaultTermWidth = 80 ) // A writer that syncs writes with a mutex and, if the output is a TTY, clears before newlines. @@ -252,10 +253,12 @@ func showProgress( pbs = append(pbs, s.GetProgress()) } + var errTermGetSize bool termWidth, _, err := terminal.GetSize(int(os.Stdout.Fd())) if err != nil && stdoutTTY { logger.WithError(err).Warn("error getting terminal size") - termWidth = 80 // TODO: something safer, return error? + termWidth = defaultTermWidth + errTermGetSize = true } // Get the longest left side string length, to align progress bars @@ -330,12 +333,20 @@ func showProgress( outMutex.Unlock() return case <-winch: - // More responsive progress bar resizing on platforms with SIGWINCH (*nix) - termWidth, _, _ = terminal.GetSize(fd) + if !errTermGetSize { + // More responsive progress bar resizing on platforms with SIGWINCH (*nix) + termWidth, _, err = terminal.GetSize(fd) + if err != nil { + termWidth = defaultTermWidth + } + } case <-ticker.C: // Default ticker-based progress bar resizing - if winch == nil { - termWidth, _, _ = terminal.GetSize(fd) + if !errTermGetSize && winch == nil { + termWidth, _, err = terminal.GetSize(fd) + if err != nil { + termWidth = defaultTermWidth + } } } renderProgressBars(true) diff --git a/ui/form_fields.go b/ui/form_fields.go index 52735142255..e8c04ca7d74 100644 --- a/ui/form_fields.go +++ b/ui/form_fields.go @@ -21,6 +21,7 @@ package ui import ( + "bufio" "io" "os" "strings" @@ -122,6 +123,16 @@ func (f PasswordField) GetContents(r io.Reader) (string, error) { return "", errors.New("Cannot read password from the supplied terminal") } password, err := terminal.ReadPassword(int(stdin.Fd())) + if err != nil { + // Possibly running on Cygwin/mintty which doesn't emulate + // pseudo terminals properly, so fallback to plain text input. + // Note that passwords will be echoed if this is the case. + // See https://github.com/mintty/mintty/issues/56 + // A workaround is to use winpty or mintty compiled with + // Cygwin >=3.1.0 which supports the new ConPTY Windows API. + bufR := bufio.NewReader(r) + password, err = bufR.ReadBytes('\n') + } return string(password), err }