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 (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/wrappedreadline"
|
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||||
"github.com/hashicorp/terraform/repl"
|
"github.com/hashicorp/terraform/repl"
|
||||||
|
|
||||||
"github.com/chzyer/readline"
|
|
||||||
"github.com/mitchellh/cli"
|
"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
|
// Setup the UI so we can output directly to stdout
|
||||||
ui := &cli.BasicUi{
|
ui := &cli.BasicUi{
|
||||||
Writer: c.Stdout(),
|
Writer: wrappedstreams.Stdout(),
|
||||||
ErrorWriter: c.Stderr(),
|
ErrorWriter: wrappedstreams.Stderr(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// IO Loop
|
// IO Loop
|
||||||
|
@ -82,7 +80,7 @@ func (c *ConsoleCommand) Run(args []string) int {
|
||||||
|
|
||||||
func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int {
|
func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int {
|
||||||
var lastResult string
|
var lastResult string
|
||||||
scanner := bufio.NewScanner(c.Stdin())
|
scanner := bufio.NewScanner(wrappedstreams.Stdin())
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
// Handle it. If there is an error exit immediately
|
// Handle it. If there is an error exit immediately
|
||||||
result, err := session.Handle(strings.TrimSpace(scanner.Text()))
|
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
|
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 {
|
func (c *ConsoleCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: terraform console [options] [DIR]
|
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"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/helper/experiment"
|
"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/state"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/mitchellh/colorstring"
|
"github.com/mitchellh/colorstring"
|
||||||
"github.com/mitchellh/panicwrap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Meta are the meta-options that are available on all or most commands.
|
// 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.
|
// StdinPiped returns true if the input is piped.
|
||||||
func (m *Meta) StdinPiped() bool {
|
func (m *Meta) StdinPiped() bool {
|
||||||
fi, err := m.Stdin().Stat()
|
fi, err := wrappedstreams.Stdin().Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If there is an error, let's just say its not piped
|
// If there is an error, let's just say its not piped
|
||||||
return false
|
return false
|
||||||
|
@ -323,36 +322,6 @@ func (m *Meta) StdinPiped() bool {
|
||||||
return fi.Mode()&os.ModeNamedPipe != 0
|
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
|
// contextOpts returns the options to use to initialize a Terraform
|
||||||
// context with the settings from this Meta.
|
// context with the settings from this Meta.
|
||||||
func (m *Meta) contextOpts() *terraform.ContextOpts {
|
func (m *Meta) contextOpts() *terraform.ContextOpts {
|
||||||
|
|
|
@ -10,38 +10,24 @@
|
||||||
package wrappedreadline
|
package wrappedreadline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/chzyer/readline"
|
"github.com/chzyer/readline"
|
||||||
)
|
|
||||||
|
|
||||||
// These are the file descriptor numbers for the original stdin, stdout, stderr
|
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||||
// 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")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Override overrides the values in readline.Config that need to be
|
// Override overrides the values in readline.Config that need to be
|
||||||
// set with wrapped values.
|
// set with wrapped values.
|
||||||
func Override(cfg *readline.Config) *readline.Config {
|
func Override(cfg *readline.Config) *readline.Config {
|
||||||
cfg.Stdin = Stdin
|
cfg.Stdin = wrappedstreams.Stdin()
|
||||||
cfg.Stdout = Stdout
|
cfg.Stdout = wrappedstreams.Stdout()
|
||||||
cfg.Stderr = Stderr
|
cfg.Stderr = wrappedstreams.Stderr()
|
||||||
|
|
||||||
cfg.FuncGetWidth = TerminalWidth
|
cfg.FuncGetWidth = TerminalWidth
|
||||||
cfg.FuncIsTerminal = IsTerminal
|
cfg.FuncIsTerminal = IsTerminal
|
||||||
|
|
||||||
var rm RawMode
|
rm := RawMode{StdinFd: int(wrappedstreams.Stdin().Fd())}
|
||||||
cfg.FuncMakeRaw = rm.Enter
|
cfg.FuncMakeRaw = rm.Enter
|
||||||
cfg.FuncExitRaw = rm.Exit
|
cfg.FuncExitRaw = rm.Exit
|
||||||
|
|
||||||
|
@ -56,7 +42,9 @@ func IsTerminal() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same implementation as readline but with our custom fds
|
// 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.
|
// TerminalWidth gets the terminal width in characters.
|
||||||
|
@ -70,11 +58,13 @@ func TerminalWidth() int {
|
||||||
|
|
||||||
// RawMode is a helper for entering and exiting raw mode.
|
// RawMode is a helper for entering and exiting raw mode.
|
||||||
type RawMode struct {
|
type RawMode struct {
|
||||||
|
StdinFd int
|
||||||
|
|
||||||
state *readline.State
|
state *readline.State
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RawMode) Enter() (err error) {
|
func (r *RawMode) Enter() (err error) {
|
||||||
r.state, err = readline.MakeRaw(StdinFd)
|
r.state, err = readline.MakeRaw(r.StdinFd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,5 +73,5 @@ func (r *RawMode) Exit() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return readline.Restore(StdinFd, r.state)
|
return readline.Restore(r.StdinFd, r.state)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,18 @@ package wrappedreadline
|
||||||
import (
|
import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getWidth impl for Unix
|
// getWidth impl for Unix
|
||||||
func getWidth() int {
|
func getWidth() int {
|
||||||
w := getWidthFd(StdoutFd)
|
stdoutFd := int(wrappedstreams.Stdout().Fd())
|
||||||
|
stderrFd := int(wrappedstreams.Stderr().Fd())
|
||||||
|
|
||||||
|
w := getWidthFd(stdoutFd)
|
||||||
if w < 0 {
|
if w < 0 {
|
||||||
w = getWidthFd(StderrFd)
|
w = getWidthFd(stderrFd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return w
|
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