Skip to content

Commit

Permalink
replace our user input handling with survey package (#5142)
Browse files Browse the repository at this point in the history
* replace our own input handling with survey package

* replace our own input handling with survey package

* add unit tests for affected prompt functions
  • Loading branch information
MarlonGamez authored Dec 14, 2020
1 parent 9422d28 commit ff0d65c
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 26 deletions.
50 changes: 24 additions & 26 deletions pkg/skaffold/initializer/prompt/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ limitations under the License.
package prompt

import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"

Expand All @@ -35,6 +34,7 @@ var (
BuildConfigFunc = buildConfig
PortForwardResourceFunc = portForwardResource
askOne = survey.AskOne
ask = survey.Ask
)

func buildConfig(image string, choices []string) (string, error) {
Expand Down Expand Up @@ -64,36 +64,34 @@ func WriteSkaffoldConfig(out io.Writer, pipeline []byte, generatedManifests map[
manifestString = ", along with the generated k8s manifests,"
}

reader := bufio.NewReader(os.Stdin)
confirmLoop:
for {
fmt.Fprintf(out, "Do you want to write this configuration%s to %s? [y/n]: ", manifestString, filePath)

response, err := reader.ReadString('\n')
if err != nil {
return true, fmt.Errorf("reading user confirmation: %w", err)
}

response = strings.ToLower(strings.TrimSpace(response))
switch response {
case "y", "yes":
break confirmLoop
case "n", "no":
return true, nil
}
var response bool
prompt := &survey.Confirm{
Message: fmt.Sprintf("Do you want to write this configuration%s to %s?", manifestString, filePath),
}
err := askOne(prompt, &response, nil)
if err != nil {
return true, fmt.Errorf("reading user confirmation: %w", err)
}
return false, nil

return !response, nil
}

// PortForwardResource prompts the user to give a port to forward the current resource on
func portForwardResource(out io.Writer, imageName string) (int, error) {
reader := bufio.NewReader(os.Stdin)

fmt.Fprintf(out, "Select port to forward for %s (leave blank for none): ", imageName)

response, err := reader.ReadString('\n')
var response string
prompt := &survey.Question{
Prompt: &survey.Input{Message: fmt.Sprintf("Select port to forward for %s (leave blank for none): ", imageName)},
Validate: func(val interface{}) error {
str := val.(string)
if _, err := strconv.Atoi(str); err != nil {
return errors.New("response must be a number, or empty")
}
return nil
},
}
err := ask([]*survey.Question{prompt}, &response)
if err != nil {
return 0, fmt.Errorf("reading user confirmation: %w", err)
return 0, fmt.Errorf("reading user input: %w", err)
}

response = strings.ToLower(strings.TrimSpace(response))
Expand Down
96 changes: 96 additions & 0 deletions pkg/skaffold/initializer/prompt/prompt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,102 @@ import (
"github.com/GoogleContainerTools/skaffold/testutil"
)

func TestWriteSkaffoldConfig(t *testing.T) {
tests := []struct {
description string
config *latest.SkaffoldConfig
promptResponse bool
expectedDone bool
shouldErr bool
}{
{
description: "yes response",
config: &latest.SkaffoldConfig{},
promptResponse: true,
expectedDone: false,
shouldErr: false,
},
{
description: "no response",
config: &latest.SkaffoldConfig{},
promptResponse: false,
expectedDone: true,
shouldErr: false,
},
{
description: "error",
config: &latest.SkaffoldConfig{},
promptResponse: false,
expectedDone: true,
shouldErr: true,
},
}
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
t.Override(&askOne, func(_ survey.Prompt, response interface{}, _ ...survey.AskOpt) error {
r := response.(*bool)
*r = test.promptResponse

if test.shouldErr {
return errors.New("error")
}
return nil
})

done, err := WriteSkaffoldConfig(ioutil.Discard, []byte{}, nil, "")
t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expectedDone, done)
})
}
}

func TestPortForwardResource(t *testing.T) {
tests := []struct {
description string
config *latest.SkaffoldConfig
promptResponse string
expected int
shouldErr bool
}{
{
description: "valid response",
config: &latest.SkaffoldConfig{},
promptResponse: "8080",
expected: 8080,
shouldErr: false,
},
{
description: "empty response",
config: &latest.SkaffoldConfig{},
promptResponse: "",
expected: 0,
shouldErr: false,
},
{
description: "error",
config: &latest.SkaffoldConfig{},
promptResponse: "",
expected: 0,
shouldErr: true,
},
}
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
t.Override(&ask, func(_ []*survey.Question, response interface{}, _ ...survey.AskOpt) error {
r := response.(*string)
*r = test.promptResponse

if test.shouldErr {
return errors.New("error")
}
return nil
})

port, err := portForwardResource(ioutil.Discard, "image-name")
t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expected, port)
})
}
}

func TestConfirmInitOptions(t *testing.T) {
tests := []struct {
description string
Expand Down

0 comments on commit ff0d65c

Please sign in to comment.