From 9422d28e2b3ad0ec8ca6a5e643b4e9ce1166278a Mon Sep 17 00:00:00 2001 From: Marlon Gamez Date: Mon, 14 Dec 2020 09:53:37 -0800 Subject: [PATCH] new init prompt function and helper functions (#5141) * new prompt function and helper functions * use survey.Confirm instead of survey.Select * use yamltags.GetYamlTags --- pkg/skaffold/initializer/prompt/prompt.go | 30 +++++ .../initializer/prompt/prompt_test.go | 76 +++++++++++++ pkg/skaffold/initializer/util/util.go | 47 ++++++++ pkg/skaffold/initializer/util/util_test.go | 103 ++++++++++++++++++ 4 files changed, 256 insertions(+) create mode 100644 pkg/skaffold/initializer/prompt/prompt_test.go create mode 100644 pkg/skaffold/initializer/util/util.go create mode 100644 pkg/skaffold/initializer/util/util_test.go diff --git a/pkg/skaffold/initializer/prompt/prompt.go b/pkg/skaffold/initializer/prompt/prompt.go index e031f2e8317..5cfb30fac5b 100644 --- a/pkg/skaffold/initializer/prompt/prompt.go +++ b/pkg/skaffold/initializer/prompt/prompt.go @@ -25,12 +25,16 @@ import ( "strings" "github.com/AlecAivazis/survey/v2" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/util" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" ) // For testing var ( BuildConfigFunc = buildConfig PortForwardResourceFunc = portForwardResource + askOne = survey.AskOne ) func buildConfig(image string, choices []string) (string, error) { @@ -100,3 +104,29 @@ func portForwardResource(out io.Writer, imageName string) (int, error) { responseInt, _ := strconv.Atoi(response) return responseInt, nil } + +// ConfirmInitOptions prompts the user to confirm that they are okay with what skaffold will do if they +// run with the current config +func ConfirmInitOptions(out io.Writer, config *latest.SkaffoldConfig) (bool, error) { + builders := strings.Join(util.ListBuilders(&config.Build), ",") + deployers := strings.Join(util.ListDeployers(&config.Deploy), ",") + + fmt.Fprintf(out, `If you choose to continue, skaffold will do the following: + - Create a skaffold config file for you + - Build your application using %s + - Deploy your application to your current kubernetes context using %s + +`, builders, deployers) + + var response bool + prompt := &survey.Confirm{ + Message: "Would you like to continue?", + } + err := askOne(prompt, &response, nil) + if err != nil { + return true, err + } + + // invert response because "no" == done and "yes" == !done + return !response, nil +} diff --git a/pkg/skaffold/initializer/prompt/prompt_test.go b/pkg/skaffold/initializer/prompt/prompt_test.go new file mode 100644 index 00000000000..edc8202cfe3 --- /dev/null +++ b/pkg/skaffold/initializer/prompt/prompt_test.go @@ -0,0 +1,76 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package prompt + +import ( + "errors" + "io/ioutil" + "testing" + + "github.com/AlecAivazis/survey/v2" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" + "github.com/GoogleContainerTools/skaffold/testutil" +) + +func TestConfirmInitOptions(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 := ConfirmInitOptions(ioutil.Discard, test.config) + t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expectedDone, done) + }) + } +} diff --git a/pkg/skaffold/initializer/util/util.go b/pkg/skaffold/initializer/util/util.go new file mode 100644 index 00000000000..9485f7b3c28 --- /dev/null +++ b/pkg/skaffold/initializer/util/util.go @@ -0,0 +1,47 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/misc" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/yamltags" +) + +// ListBuilders returns a list of builder names being used in the given build config. +func ListBuilders(build *latest.BuildConfig) []string { + if build == nil { + return []string{} + } + + results := util.NewStringSet() + for _, artifact := range build.Artifacts { + results.Insert(misc.ArtifactType(artifact)) + } + + return results.ToList() +} + +// ListDeployers returns a list of deployer names being used in the given deploy config. +func ListDeployers(deploy *latest.DeployConfig) []string { + if deploy == nil { + return []string{} + } + + return yamltags.GetYamlTags(deploy.DeployType) +} diff --git a/pkg/skaffold/initializer/util/util_test.go b/pkg/skaffold/initializer/util/util_test.go new file mode 100644 index 00000000000..a91cdf85c73 --- /dev/null +++ b/pkg/skaffold/initializer/util/util_test.go @@ -0,0 +1,103 @@ +/* +Copyright 2020 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "testing" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" + "github.com/GoogleContainerTools/skaffold/testutil" +) + +func TestListBuilders(t *testing.T) { + tests := []struct { + description string + build *latest.BuildConfig + expected []string + }{ + { + description: "nil config", + build: nil, + expected: []string{}, + }, + { + description: "multiple same builder config", + build: &latest.BuildConfig{ + Artifacts: []*latest.Artifact{ + {ImageName: "img1", ArtifactType: latest.ArtifactType{DockerArtifact: &latest.DockerArtifact{}}}, + {ImageName: "img2", ArtifactType: latest.ArtifactType{DockerArtifact: &latest.DockerArtifact{}}}, + }, + }, + expected: []string{"docker"}, + }, + { + description: "different builders config", + build: &latest.BuildConfig{ + Artifacts: []*latest.Artifact{ + {ImageName: "img1", ArtifactType: latest.ArtifactType{DockerArtifact: &latest.DockerArtifact{}}}, + {ImageName: "img2", ArtifactType: latest.ArtifactType{JibArtifact: &latest.JibArtifact{}}}, + }, + }, + expected: []string{"docker", "jib"}, + }, + } + for _, test := range tests { + testutil.Run(t, test.description, func(t *testutil.T) { + got := ListBuilders(test.build) + t.CheckDeepEqual(test.expected, got) + }) + } +} + +func TestListDeployers(t *testing.T) { + tests := []struct { + description string + deploy *latest.DeployConfig + expected []string + }{ + { + description: "nil config", + deploy: nil, + expected: []string{}, + }, + { + description: "single deployer config", + deploy: &latest.DeployConfig{ + DeployType: latest.DeployType{ + KubectlDeploy: &latest.KubectlDeploy{}, + }, + }, + expected: []string{"kubectl"}, + }, + { + description: "multiple deployers config", + deploy: &latest.DeployConfig{ + DeployType: latest.DeployType{ + HelmDeploy: &latest.HelmDeploy{}, + KubectlDeploy: &latest.KubectlDeploy{}, + }, + }, + expected: []string{"helm", "kubectl"}, + }, + } + for _, test := range tests { + testutil.Run(t, test.description, func(t *testutil.T) { + got := ListDeployers(test.deploy) + t.CheckDeepEqual(test.expected, got) + }) + } +}