open-nomad/command/ui/writer_ui.go
Charlie Voiselle 61f997d806
Add WriterUI (#17051)
This special purpose UI provides commands that can benefit from direct
access to the io.Reader and io.Writers of the base cli.Ui. It can
traverse a chain of ColoredUis to find the base. Currently, it can
retrieve writers from a cli.BasicUi (or cli.MockUi for testing).

Renames ui.go and ui_test.go to log_ui.go and log_ui_test.go
2023-05-02 13:40:44 -04:00

84 lines
2.3 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package ui
import (
"errors"
"fmt"
"io"
"github.com/mitchellh/cli"
)
// WriterUI is an implementation of the cli.Ui interface which can be used for
// commands that need to have direct access to the underlying UI readers and
// writers.
type WriterUI struct {
// Ui is the wrapped cli.Ui that supplies the functions for the thin shims
Ui cli.Ui
reader io.Reader
writer io.Writer
errorWriter io.Writer
// baseUi stores the basic UI that was used to create this WriterUI. It
// allows us to call its functions and not implement them again.
baseUi cli.Ui
}
// NewWriterUI generates a new cli.Ui that can be used for commands that
// need access to the underlying UI's writers for copying large amounts of
// data without local buffering. The caller is required to pass a UI
// chain ending in a cli.BasicUi (or a cli.MockUi for testing).
//
// Currently, the UIs in the chain need to be pointers to a cli.ColoredUi,
// cli.BasicUi, or cli.MockUi to work correctly.
func NewWriterUI(ui cli.Ui) (*WriterUI, error) {
var done bool
wUI := WriterUI{Ui: ui}
for !done {
if ui == nil {
break
}
switch u := ui.(type) {
case *cli.MockUi:
wUI.reader = u.InputReader
wUI.writer = u.OutputWriter
wUI.errorWriter = u.ErrorWriter
wUI.baseUi = u
done = true
case *cli.BasicUi:
wUI.reader = u.Reader
wUI.writer = u.Writer
wUI.errorWriter = u.ErrorWriter
wUI.baseUi = u
done = true
case *cli.ColoredUi:
ui = u.Ui
default:
return nil, fmt.Errorf("writer ui: unsupported Ui type: %T", ui)
}
}
if !done {
return nil, errors.New("failed to generate command UI")
}
return &wUI, nil
}
func (w *WriterUI) InputReader() io.Reader { return w.reader }
func (w *WriterUI) OutputWriter() io.Writer { return w.writer }
func (w *WriterUI) ErrorWriter() io.Writer { return w.errorWriter }
func (w *WriterUI) Output(message string) { w.Ui.Output(message) }
func (w *WriterUI) Info(message string) { w.Ui.Info(message) }
func (w *WriterUI) Warn(message string) { w.Ui.Warn(message) }
func (w *WriterUI) Error(message string) { w.Ui.Error(message) }
func (w *WriterUI) Ask(query string) (string, error) { return w.Ui.Ask(query) }
func (w *WriterUI) AskSecret(query string) (string, error) { return w.Ui.AskSecret(query) }