Improve the error message for pulumi new
when the template doesn't exist (#1823)
And offer distance-based suggestions.
This commit is contained in:
parent
ddd83fafc4
commit
5586f4ecad
8
Gopkg.lock
generated
8
Gopkg.lock
generated
|
@ -362,6 +362,12 @@
|
|||
revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0"
|
||||
version = "v1.1.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/texttheater/golang-levenshtein"
|
||||
packages = ["levenshtein"]
|
||||
revision = "d188e65d659ef53fcdb0691c12f1bba64928b649"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/uber/jaeger-client-go"
|
||||
packages = [
|
||||
|
@ -578,6 +584,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "71208477393825ddcf9e60bd0a6855758c05f49ec560fd9e5ba6336592a18da0"
|
||||
inputs-digest = "d6db93501077426a275193a3d77e69cc4fe68fd80603907438fcb0503d7817a0"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/texttheater/golang-levenshtein/levenshtein"
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
|
||||
|
@ -216,6 +217,15 @@ func retrievePulumiTemplates(templateName string, offline bool) (TemplateReposit
|
|||
subDir := templateDir
|
||||
if templateName != "" {
|
||||
subDir = filepath.Join(subDir, templateName)
|
||||
|
||||
// Provide a nicer error message when the template can't be found (dir doesn't exist).
|
||||
_, err := os.Stat(subDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return TemplateRepository{}, newTemplateNotFoundError(templateDir, templateName)
|
||||
}
|
||||
contract.IgnoreError(err)
|
||||
}
|
||||
}
|
||||
|
||||
return TemplateRepository{
|
||||
|
@ -472,6 +482,40 @@ func newExistingFilesError(existing []string) error {
|
|||
return errors.New(message)
|
||||
}
|
||||
|
||||
// newTemplateNotFoundError returns an error for when the template doesn't exist,
|
||||
// offering distance-based suggestions in the error message.
|
||||
func newTemplateNotFoundError(templateDir string, templateName string) error {
|
||||
message := fmt.Sprintf("template '%s' not found", templateName)
|
||||
|
||||
// Attempt to read the directory to offer suggestions.
|
||||
infos, err := ioutil.ReadDir(templateDir)
|
||||
if err != nil {
|
||||
contract.IgnoreError(err)
|
||||
return errors.New(message)
|
||||
}
|
||||
|
||||
// Get suggestions based on levenshtein distance.
|
||||
suggestions := []string{}
|
||||
const minDistance = 2
|
||||
op := levenshtein.DefaultOptions
|
||||
for _, info := range infos {
|
||||
distance := levenshtein.DistanceForStrings([]rune(templateName), []rune(info.Name()), op)
|
||||
if distance <= minDistance {
|
||||
suggestions = append(suggestions, info.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// Build-up error message with suggestions.
|
||||
if len(suggestions) > 0 {
|
||||
message = message + "\n\nDid you mean this?\n"
|
||||
for _, suggestion := range suggestions {
|
||||
message = message + fmt.Sprintf("\t%s\n", suggestion)
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New(message)
|
||||
}
|
||||
|
||||
// transform returns a new string with ${PROJECT} and ${DESCRIPTION} replaced by
|
||||
// the value of projectName and projectDescription.
|
||||
func transform(content string, projectName string, projectDescription string) string {
|
||||
|
|
Loading…
Reference in a new issue