github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/initializer/prompt/prompt.go (about) 1 /* 2 Copyright 2020 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package prompt 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "strconv" 24 "strings" 25 26 "github.com/AlecAivazis/survey/v2" 27 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/util" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 30 ) 31 32 // For testing 33 var ( 34 BuildConfigFunc = buildConfig 35 ChooseBuildersFunc = chooseBuilders 36 PortForwardResourceFunc = portForwardResource 37 askOne = survey.AskOne 38 ask = survey.Ask 39 ) 40 41 func buildConfig(image string, choices []string) (string, error) { 42 var selectedBuildConfig string 43 prompt := &survey.Select{ 44 Message: fmt.Sprintf("Choose the builder to build image %s", image), 45 Options: choices, 46 PageSize: 15, 47 } 48 err := survey.AskOne(prompt, &selectedBuildConfig, nil) 49 if err != nil { 50 return "", err 51 } 52 53 return selectedBuildConfig, nil 54 } 55 56 func WriteSkaffoldConfig(out io.Writer, pipeline []byte, generatedManifests map[string][]byte, filePath string) (bool, error) { 57 fmt.Fprintln(out, string(pipeline)) 58 59 for path, manifest := range generatedManifests { 60 fmt.Fprintln(out, path, "-", string(manifest)) 61 } 62 63 manifestString := "" 64 if len(generatedManifests) > 0 { 65 manifestString = ", along with the generated k8s manifests," 66 } 67 68 var response bool 69 prompt := &survey.Confirm{ 70 Message: fmt.Sprintf("Do you want to write this configuration%s to %s?", manifestString, filePath), 71 } 72 err := askOne(prompt, &response, nil) 73 if err != nil { 74 return true, fmt.Errorf("reading user confirmation: %w", err) 75 } 76 77 return !response, nil 78 } 79 80 // chooseBuilders prompts the user to select which builders they'd like to create associated kubernetes manifests for 81 func chooseBuilders(builders []string) ([]string, error) { 82 chosen := []string{} 83 prompt := &survey.MultiSelect{ 84 Message: "Which builders would you like to create kubernetes resources for?", 85 Options: builders, 86 } 87 err := askOne(prompt, &chosen) 88 if err != nil { 89 return []string{}, fmt.Errorf("getting user choices") 90 } 91 92 return chosen, err 93 } 94 95 // PortForwardResource prompts the user to give a port to forward the current resource on 96 func portForwardResource(out io.Writer, imageName string) (int, error) { 97 var response string 98 prompt := &survey.Question{ 99 Prompt: &survey.Input{Message: fmt.Sprintf("Select port to forward for %s (leave blank for none):", imageName)}, 100 Validate: func(val interface{}) error { 101 str := val.(string) 102 if _, err := strconv.Atoi(str); err != nil && str != "" { 103 return errors.New("response must be a number, or empty") 104 } 105 return nil 106 }, 107 } 108 err := ask([]*survey.Question{prompt}, &response) 109 if err != nil { 110 return 0, fmt.Errorf("reading user input: %w", err) 111 } 112 113 response = strings.ToLower(strings.TrimSpace(response)) 114 if response == "" { 115 return 0, nil 116 } 117 118 responseInt, _ := strconv.Atoi(response) 119 return responseInt, nil 120 } 121 122 // ConfirmInitOptions prompts the user to confirm that they are okay with what skaffold will do if they 123 // run with the current config 124 func ConfirmInitOptions(out io.Writer, config *latest.SkaffoldConfig) (bool, error) { 125 builders := strings.Join(util.ListBuilders(&config.Build), ",") 126 deployers := strings.Join(util.ListDeployers(&config.Deploy), ",") 127 128 fmt.Fprintf(out, `If you choose to continue, skaffold will do the following: 129 - Create a skaffold config file for you 130 - Build your application using %s 131 - Deploy your application to your current kubernetes context using %s 132 133 `, builders, deployers) 134 135 var response bool 136 prompt := &survey.Confirm{ 137 Message: "Would you like to continue?", 138 } 139 err := askOne(prompt, &response, nil) 140 if err != nil { 141 return true, err 142 } 143 144 // invert response because "no" == done and "yes" == !done 145 return !response, nil 146 }