command: split out and tag code so compilation works on Solaris
The readline library doesn't support Solaris. For now, we'll just not support console there.
This commit is contained in:
parent
0232b39db6
commit
1a6056b287
|
@ -3,14 +3,12 @@ package command
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/wrappedreadline"
|
||||
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||
"github.com/hashicorp/terraform/repl"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -63,8 +61,8 @@ func (c *ConsoleCommand) Run(args []string) int {
|
|||
|
||||
// Setup the UI so we can output directly to stdout
|
||||
ui := &cli.BasicUi{
|
||||
Writer: c.Stdout(),
|
||||
ErrorWriter: c.Stderr(),
|
||||
Writer: wrappedstreams.Stdout(),
|
||||
ErrorWriter: wrappedstreams.Stderr(),
|
||||
}
|
||||
|
||||
// IO Loop
|
||||
|
@ -82,7 +80,7 @@ func (c *ConsoleCommand) Run(args []string) int {
|
|||
|
||||
func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int {
|
||||
var lastResult string
|
||||
scanner := bufio.NewScanner(c.Stdin())
|
||||
scanner := bufio.NewScanner(wrappedstreams.Stdin())
|
||||
for scanner.Scan() {
|
||||
// Handle it. If there is an error exit immediately
|
||||
result, err := session.Handle(strings.TrimSpace(scanner.Text()))
|
||||
|
@ -101,50 +99,6 @@ func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (c *ConsoleCommand) modeInteractive(session *repl.Session, ui cli.Ui) int {
|
||||
// Configure input
|
||||
l, err := readline.NewEx(wrappedreadline.Override(&readline.Config{
|
||||
Prompt: "> ",
|
||||
InterruptPrompt: "^C",
|
||||
EOFPrompt: "exit",
|
||||
HistorySearchFold: true,
|
||||
}))
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error initializing console: %s",
|
||||
err))
|
||||
return 1
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
for {
|
||||
// Read a line
|
||||
line, err := l.Readline()
|
||||
if err == readline.ErrInterrupt {
|
||||
if len(line) == 0 {
|
||||
break
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
out, err := session.Handle(line)
|
||||
if err == repl.ErrSessionExit {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
ui.Output(out)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *ConsoleCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: terraform console [options] [DIR]
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
// +build !solaris
|
||||
|
||||
// The readline library we use doesn't currently support solaris so
|
||||
// we just build tag it off.
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/wrappedreadline"
|
||||
"github.com/hashicorp/terraform/repl"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func (c *ConsoleCommand) modeInteractive(session *repl.Session, ui cli.Ui) int {
|
||||
// Configure input
|
||||
l, err := readline.NewEx(wrappedreadline.Override(&readline.Config{
|
||||
Prompt: "> ",
|
||||
InterruptPrompt: "^C",
|
||||
EOFPrompt: "exit",
|
||||
HistorySearchFold: true,
|
||||
}))
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error initializing console: %s",
|
||||
err))
|
||||
return 1
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
for {
|
||||
// Read a line
|
||||
line, err := l.Readline()
|
||||
if err == readline.ErrInterrupt {
|
||||
if len(line) == 0 {
|
||||
break
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
out, err := session.Handle(line)
|
||||
if err == repl.ErrSessionExit {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
ui.Output(out)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// +build solaris
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/repl"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func (c *ConsoleCommand) modeInteractive(session *repl.Session, ui cli.Ui) int {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"The readline library Terraform currently uses for the interactive\n" +
|
||||
"console is not supported by Solaris. Interactive mode is therefore\n" +
|
||||
"not supported on Solaris currently."))
|
||||
return 1
|
||||
}
|
|
@ -15,12 +15,11 @@ import (
|
|||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/helper/experiment"
|
||||
"github.com/hashicorp/terraform/helper/wrappedreadline"
|
||||
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/colorstring"
|
||||
"github.com/mitchellh/panicwrap"
|
||||
)
|
||||
|
||||
// Meta are the meta-options that are available on all or most commands.
|
||||
|
@ -314,7 +313,7 @@ func (m *Meta) Input() bool {
|
|||
|
||||
// StdinPiped returns true if the input is piped.
|
||||
func (m *Meta) StdinPiped() bool {
|
||||
fi, err := m.Stdin().Stat()
|
||||
fi, err := wrappedstreams.Stdin().Stat()
|
||||
if err != nil {
|
||||
// If there is an error, let's just say its not piped
|
||||
return false
|
||||
|
@ -323,36 +322,6 @@ func (m *Meta) StdinPiped() bool {
|
|||
return fi.Mode()&os.ModeNamedPipe != 0
|
||||
}
|
||||
|
||||
// Stdin returns the stdin for this command.
|
||||
func (m *Meta) Stdin() *os.File {
|
||||
stdin := os.Stdin
|
||||
if panicwrap.Wrapped(nil) {
|
||||
stdin = wrappedreadline.Stdin
|
||||
}
|
||||
|
||||
return stdin
|
||||
}
|
||||
|
||||
// Stdout returns the stdout for this command.
|
||||
func (m *Meta) Stdout() *os.File {
|
||||
stdout := os.Stdout
|
||||
if panicwrap.Wrapped(nil) {
|
||||
stdout = wrappedreadline.Stdout
|
||||
}
|
||||
|
||||
return stdout
|
||||
}
|
||||
|
||||
// Stderr returns the stderr for this command.
|
||||
func (m *Meta) Stderr() *os.File {
|
||||
stderr := os.Stderr
|
||||
if panicwrap.Wrapped(nil) {
|
||||
stderr = wrappedreadline.Stderr
|
||||
}
|
||||
|
||||
return stderr
|
||||
}
|
||||
|
||||
// contextOpts returns the options to use to initialize a Terraform
|
||||
// context with the settings from this Meta.
|
||||
func (m *Meta) contextOpts() *terraform.ContextOpts {
|
||||
|
|
|
@ -10,38 +10,24 @@
|
|||
package wrappedreadline
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
)
|
||||
|
||||
// These are the file descriptor numbers for the original stdin, stdout, stderr
|
||||
// streams from the parent process.
|
||||
const (
|
||||
StdinFd = 3
|
||||
StdoutFd = 4
|
||||
StderrFd = 5
|
||||
)
|
||||
|
||||
// These are the *os.File values for the standard streams.
|
||||
var (
|
||||
Stdin = os.NewFile(uintptr(StdinFd), "stdin")
|
||||
Stdout = os.NewFile(uintptr(StdoutFd), "stdout")
|
||||
Stderr = os.NewFile(uintptr(StderrFd), "stderr")
|
||||
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||
)
|
||||
|
||||
// Override overrides the values in readline.Config that need to be
|
||||
// set with wrapped values.
|
||||
func Override(cfg *readline.Config) *readline.Config {
|
||||
cfg.Stdin = Stdin
|
||||
cfg.Stdout = Stdout
|
||||
cfg.Stderr = Stderr
|
||||
cfg.Stdin = wrappedstreams.Stdin()
|
||||
cfg.Stdout = wrappedstreams.Stdout()
|
||||
cfg.Stderr = wrappedstreams.Stderr()
|
||||
|
||||
cfg.FuncGetWidth = TerminalWidth
|
||||
cfg.FuncIsTerminal = IsTerminal
|
||||
|
||||
var rm RawMode
|
||||
rm := RawMode{StdinFd: int(wrappedstreams.Stdin().Fd())}
|
||||
cfg.FuncMakeRaw = rm.Enter
|
||||
cfg.FuncExitRaw = rm.Exit
|
||||
|
||||
|
@ -56,7 +42,9 @@ func IsTerminal() bool {
|
|||
}
|
||||
|
||||
// Same implementation as readline but with our custom fds
|
||||
return readline.IsTerminal(StdinFd) && (readline.IsTerminal(StdoutFd) || readline.IsTerminal(StderrFd))
|
||||
return readline.IsTerminal(int(wrappedstreams.Stdin().Fd())) &&
|
||||
(readline.IsTerminal(int(wrappedstreams.Stdout().Fd())) ||
|
||||
readline.IsTerminal(int(wrappedstreams.Stderr().Fd())))
|
||||
}
|
||||
|
||||
// TerminalWidth gets the terminal width in characters.
|
||||
|
@ -70,11 +58,13 @@ func TerminalWidth() int {
|
|||
|
||||
// RawMode is a helper for entering and exiting raw mode.
|
||||
type RawMode struct {
|
||||
StdinFd int
|
||||
|
||||
state *readline.State
|
||||
}
|
||||
|
||||
func (r *RawMode) Enter() (err error) {
|
||||
r.state, err = readline.MakeRaw(StdinFd)
|
||||
r.state, err = readline.MakeRaw(r.StdinFd)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -83,5 +73,5 @@ func (r *RawMode) Exit() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return readline.Restore(StdinFd, r.state)
|
||||
return readline.Restore(r.StdinFd, r.state)
|
||||
}
|
||||
|
|
|
@ -5,13 +5,18 @@ package wrappedreadline
|
|||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||
)
|
||||
|
||||
// getWidth impl for Unix
|
||||
func getWidth() int {
|
||||
w := getWidthFd(StdoutFd)
|
||||
stdoutFd := int(wrappedstreams.Stdout().Fd())
|
||||
stderrFd := int(wrappedstreams.Stderr().Fd())
|
||||
|
||||
w := getWidthFd(stdoutFd)
|
||||
if w < 0 {
|
||||
w = getWidthFd(StderrFd)
|
||||
w = getWidthFd(stderrFd)
|
||||
}
|
||||
|
||||
return w
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Package wrappedstreams provides access to the standard OS streams
|
||||
// (stdin, stdout, stderr) even if wrapped under panicwrap.
|
||||
package wrappedstreams
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/mitchellh/panicwrap"
|
||||
)
|
||||
|
||||
// Stdin returns the true stdin of the process.
|
||||
func Stdin() *os.File {
|
||||
stdin := os.Stdin
|
||||
if panicwrap.Wrapped(nil) {
|
||||
stdin = wrappedStdin
|
||||
}
|
||||
|
||||
return stdin
|
||||
}
|
||||
|
||||
// Stdout returns the true stdout of the process.
|
||||
func Stdout() *os.File {
|
||||
stdout := os.Stdout
|
||||
if panicwrap.Wrapped(nil) {
|
||||
stdout = wrappedStdout
|
||||
}
|
||||
|
||||
return stdout
|
||||
}
|
||||
|
||||
// Stderr returns the true stderr of the process.
|
||||
func Stderr() *os.File {
|
||||
stderr := os.Stderr
|
||||
if panicwrap.Wrapped(nil) {
|
||||
stderr = wrappedStderr
|
||||
}
|
||||
|
||||
return stderr
|
||||
}
|
||||
|
||||
// These are the wrapped streams. There doesn't appear to be a negative
|
||||
// impact of opening these files even if the file descriptor doesn't exist.
|
||||
var (
|
||||
wrappedStdin = os.NewFile(uintptr(3), "stdin")
|
||||
wrappedStdout = os.NewFile(uintptr(4), "stdout")
|
||||
wrappedStderr = os.NewFile(uintptr(5), "stderr")
|
||||
)
|
Loading…
Reference in New Issue