Commit e0f2bcf8 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer: Add "Ask" method to Ui to ask for input

parent cbd3f595
...@@ -10,8 +10,8 @@ import ( ...@@ -10,8 +10,8 @@ import (
func testEnvironment() packer.Environment { func testEnvironment() packer.Environment {
config := packer.DefaultEnvironmentConfig() config := packer.DefaultEnvironmentConfig()
config.Ui = &packer.ReaderWriterUi{ config.Ui = &packer.ReaderWriterUi{
new(bytes.Buffer), Reader: new(bytes.Buffer),
new(bytes.Buffer), Writer: new(bytes.Buffer),
} }
env, err := packer.NewEnvironment(config) env, err := packer.NewEnvironment(config)
......
...@@ -68,7 +68,11 @@ type EnvironmentConfig struct { ...@@ -68,7 +68,11 @@ type EnvironmentConfig struct {
func DefaultEnvironmentConfig() *EnvironmentConfig { func DefaultEnvironmentConfig() *EnvironmentConfig {
config := &EnvironmentConfig{} config := &EnvironmentConfig{}
config.Commands = make([]string, 0) config.Commands = make([]string, 0)
config.Ui = &ReaderWriterUi{os.Stdin, os.Stdout} config.Ui = &ReaderWriterUi{
Reader: os.Stdin,
Writer: os.Stdout,
}
return config return config
} }
......
...@@ -13,8 +13,8 @@ import ( ...@@ -13,8 +13,8 @@ import (
func testEnvironment() Environment { func testEnvironment() Environment {
config := DefaultEnvironmentConfig() config := DefaultEnvironmentConfig()
config.Ui = &ReaderWriterUi{ config.Ui = &ReaderWriterUi{
new(bytes.Buffer), Reader: new(bytes.Buffer),
new(bytes.Buffer), Writer: new(bytes.Buffer),
} }
env, err := NewEnvironment(config) env, err := NewEnvironment(config)
...@@ -292,7 +292,10 @@ func TestEnvironmentProvisioner_Error(t *testing.T) { ...@@ -292,7 +292,10 @@ func TestEnvironmentProvisioner_Error(t *testing.T) {
func TestEnvironment_SettingUi(t *testing.T) { func TestEnvironment_SettingUi(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true) assert := asserts.NewTestingAsserts(t, true)
ui := &ReaderWriterUi{new(bytes.Buffer), new(bytes.Buffer)} ui := &ReaderWriterUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
}
config := &EnvironmentConfig{} config := &EnvironmentConfig{}
config.Ui = ui config.Ui = ui
......
...@@ -17,6 +17,15 @@ type UiServer struct { ...@@ -17,6 +17,15 @@ type UiServer struct {
ui packer.Ui ui packer.Ui
} }
func (u *Ui) Ask(query string) string {
var result string
if err := u.client.Call("Ui.Ask", query, &result); err != nil {
panic(err)
}
return result
}
func (u *Ui) Error(message string) { func (u *Ui) Error(message string) {
if err := u.client.Call("Ui.Error", message, new(interface{})); err != nil { if err := u.client.Call("Ui.Error", message, new(interface{})); err != nil {
panic(err) panic(err)
...@@ -35,6 +44,11 @@ func (u *Ui) Say(message string) { ...@@ -35,6 +44,11 @@ func (u *Ui) Say(message string) {
} }
} }
func (u *UiServer) Ask(query string, reply *string) error {
*reply = u.ui.Ask(query)
return nil
}
func (u *UiServer) Error(message *string, reply *interface{}) error { func (u *UiServer) Error(message *string, reply *interface{}) error {
u.ui.Error(*message) u.ui.Error(*message)
......
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
) )
type testUi struct { type testUi struct {
askCalled bool
askQuery string
errorCalled bool errorCalled bool
errorMessage string errorMessage string
messageCalled bool messageCalled bool
...@@ -15,6 +17,12 @@ type testUi struct { ...@@ -15,6 +17,12 @@ type testUi struct {
sayMessage string sayMessage string
} }
func (u *testUi) Ask(query string) string {
u.askCalled = true
u.askQuery = query
return "foo"
}
func (u *testUi) Error(message string) { func (u *testUi) Error(message string) {
u.errorCalled = true u.errorCalled = true
u.errorMessage = message u.errorMessage = message
...@@ -50,6 +58,11 @@ func TestUiRPC(t *testing.T) { ...@@ -50,6 +58,11 @@ func TestUiRPC(t *testing.T) {
uiClient := &Ui{client} uiClient := &Ui{client}
// Basic error and say tests // Basic error and say tests
result := uiClient.Ask("query")
assert.True(ui.askCalled, "ask should be called")
assert.Equal(ui.askQuery, "query", "should be correct")
assert.Equal(result, "foo", "should have correct result")
uiClient.Error("message") uiClient.Error("message")
assert.Equal(ui.errorMessage, "message", "message should be correct") assert.Equal(ui.errorMessage, "message", "message should be correct")
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"sync"
) )
type UiColor uint type UiColor uint
...@@ -21,6 +22,7 @@ const ( ...@@ -21,6 +22,7 @@ const (
// world. This sort of control allows us to strictly control how output // world. This sort of control allows us to strictly control how output
// is formatted and various levels of output. // is formatted and various levels of output.
type Ui interface { type Ui interface {
Ask(string) string
Say(string) Say(string)
Message(string) Message(string)
Error(string) Error(string)
...@@ -46,6 +48,11 @@ type PrefixedUi struct { ...@@ -46,6 +48,11 @@ type PrefixedUi struct {
type ReaderWriterUi struct { type ReaderWriterUi struct {
Reader io.Reader Reader io.Reader
Writer io.Writer Writer io.Writer
l sync.Mutex
}
func (u *ColoredUi) Ask(query string) string {
return u.Ui.Ask(u.colorize(query, u.Color, true))
} }
func (u *ColoredUi) Say(message string) { func (u *ColoredUi) Say(message string) {
...@@ -74,6 +81,10 @@ func (u *ColoredUi) colorize(message string, color UiColor, bold bool) string { ...@@ -74,6 +81,10 @@ func (u *ColoredUi) colorize(message string, color UiColor, bold bool) string {
return fmt.Sprintf("\033[%d;%d;40m%s\033[0m", attr, color, message) return fmt.Sprintf("\033[%d;%d;40m%s\033[0m", attr, color, message)
} }
func (u *PrefixedUi) Ask(query string) string {
return u.Ui.Ask(fmt.Sprintf("%s: %s", u.SayPrefix, query))
}
func (u *PrefixedUi) Say(message string) { func (u *PrefixedUi) Say(message string) {
u.Ui.Say(fmt.Sprintf("%s: %s", u.SayPrefix, message)) u.Ui.Say(fmt.Sprintf("%s: %s", u.SayPrefix, message))
} }
...@@ -86,7 +97,29 @@ func (u *PrefixedUi) Error(message string) { ...@@ -86,7 +97,29 @@ func (u *PrefixedUi) Error(message string) {
u.Ui.Error(fmt.Sprintf("%s: %s", u.SayPrefix, message)) u.Ui.Error(fmt.Sprintf("%s: %s", u.SayPrefix, message))
} }
func (rw *ReaderWriterUi) Ask(query string) string {
rw.l.Lock()
defer rw.l.Unlock()
log.Printf("ui: ask: %s", query)
if query != "" {
if _, err := fmt.Fprint(rw.Writer, query+" "); err != nil {
panic(err)
}
}
var line string
if _, err := fmt.Fscanln(rw.Reader, &line); err != nil {
panic(err)
}
return line
}
func (rw *ReaderWriterUi) Say(message string) { func (rw *ReaderWriterUi) Say(message string) {
rw.l.Lock()
defer rw.l.Unlock()
log.Printf("ui: %s", message) log.Printf("ui: %s", message)
_, err := fmt.Fprint(rw.Writer, message+"\n") _, err := fmt.Fprint(rw.Writer, message+"\n")
if err != nil { if err != nil {
...@@ -95,6 +128,9 @@ func (rw *ReaderWriterUi) Say(message string) { ...@@ -95,6 +128,9 @@ func (rw *ReaderWriterUi) Say(message string) {
} }
func (rw *ReaderWriterUi) Message(message string) { func (rw *ReaderWriterUi) Message(message string) {
rw.l.Lock()
defer rw.l.Unlock()
log.Printf("ui: %s", message) log.Printf("ui: %s", message)
_, err := fmt.Fprintf(rw.Writer, message+"\n") _, err := fmt.Fprintf(rw.Writer, message+"\n")
if err != nil { if err != nil {
...@@ -103,6 +139,9 @@ func (rw *ReaderWriterUi) Message(message string) { ...@@ -103,6 +139,9 @@ func (rw *ReaderWriterUi) Message(message string) {
} }
func (rw *ReaderWriterUi) Error(message string) { func (rw *ReaderWriterUi) Error(message string) {
rw.l.Lock()
defer rw.l.Unlock()
log.Printf("ui error: %s", message) log.Printf("ui error: %s", message)
_, err := fmt.Fprint(rw.Writer, message+"\n") _, err := fmt.Fprint(rw.Writer, message+"\n")
if err != nil { if err != nil {
......
...@@ -8,8 +8,8 @@ import ( ...@@ -8,8 +8,8 @@ import (
func testUi() *ReaderWriterUi { func testUi() *ReaderWriterUi {
return &ReaderWriterUi{ return &ReaderWriterUi{
new(bytes.Buffer), Reader: new(bytes.Buffer),
new(bytes.Buffer), Writer: new(bytes.Buffer),
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment