Skip to content

Commit

Permalink
Add error for missing required variable
Browse files Browse the repository at this point in the history
  • Loading branch information
paultyng committed Aug 20, 2020
1 parent fbdfd34 commit 27f8e13
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 10 deletions.
46 changes: 36 additions & 10 deletions tfexec/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ import (
"fmt"
"os/exec"
"regexp"
"strings"
)

var (
// The "Required variable not set:" case is for 0.11
missingVarErrRegexp = regexp.MustCompile(`Error: No value for required variable|Error: Required variable not set:`)
missingVarNameRegexp = regexp.MustCompile(`The root module input variable "(.+)" is not set, and has no default|Error: Required variable not set: (.+)`)

usageRegexp = regexp.MustCompile(`Too many command line arguments|^Usage: .*Options:.*|Error: Invalid -\d+ option`)

// "Could not load plugin" is present in 0.13
noInitErrRegexp = regexp.MustCompile(`Error: Could not satisfy plugin requirements|Error: Could not load plugin`)

noConfigErrRegexp = regexp.MustCompile(`Error: No configuration files`)
)

func parseError(err error, stderr string) error {
Expand All @@ -13,16 +27,22 @@ func parseError(err error, stderr string) error {
}

switch {
// case ErrTerraformNotFound.regexp.MatchString(stderr):
// return ErrTerraformNotFound
case regexp.MustCompile(usageRegexp).MatchString(stderr):
case missingVarErrRegexp.MatchString(stderr):
name := ""
names := missingVarNameRegexp.FindStringSubmatch(stderr)
for i := 1; i < len(names); i++ {
name = strings.TrimSpace(names[i])
if name != "" {
break
}
}

return &ErrMissingVar{name}
case usageRegexp.MatchString(stderr):
return &ErrCLIUsage{stderr: stderr}
case regexp.MustCompile(`Error: Could not satisfy plugin requirements`).MatchString(stderr):
return &ErrNoInit{stderr: stderr}
case regexp.MustCompile(`Error: Could not load plugin`).MatchString(stderr):
// this string is present in 0.13
case noInitErrRegexp.MatchString(stderr):
return &ErrNoInit{stderr: stderr}
case regexp.MustCompile(`Error: No configuration files`).MatchString(stderr):
case noConfigErrRegexp.MatchString(stderr):
return &ErrNoConfig{stderr: stderr}
default:
return errors.New(stderr)
Expand Down Expand Up @@ -77,8 +97,6 @@ type ErrCLIUsage struct {
stderr string
}

var usageRegexp = `Too many command line arguments|^Usage: .*Options:.*|Error: Invalid -\d+ option`

func (e *ErrCLIUsage) Error() string {
return e.stderr
}
Expand All @@ -92,3 +110,11 @@ type ErrManualEnvVar struct {
func (err *ErrManualEnvVar) Error() string {
return fmt.Sprintf("manual setting of env var %q detected", err.name)
}

type ErrMissingVar struct {
VariableName string
}

func (err *ErrMissingVar) Error() string {
return fmt.Sprintf("variable %q was required but not supplied", err.VariableName)
}
27 changes: 27 additions & 0 deletions tfexec/internal/e2etest/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,30 @@ func TestUnparsedError(t *testing.T) {
}
})
}

func TestMissingVar(t *testing.T) {
runTest(t, "var", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
err := tf.Init(context.Background())
if err != nil {
t.Fatalf("err during init: %s", err)
}

err = tf.Plan(context.Background())
if err == nil {
t.Fatalf("expected error running Plan, none returned")
}
var e *tfexec.ErrMissingVar
if !errors.As(err, &e) {
t.Fatalf("expected ErrMissingVar, got %T, %s", err, err)
}

if e.VariableName != "no_default" {
t.Fatalf("expected missing no_default, got %q", e.VariableName)
}

err = tf.Plan(context.Background(), tfexec.Var("no_default=foo"))
if err != nil {
t.Fatalf("expected no error, got %s", err)
}
})
}
6 changes: 6 additions & 0 deletions tfexec/internal/e2etest/testdata/var/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
variable "default" {
default = "foo"
}

variable "no_default" {
}

0 comments on commit 27f8e13

Please sign in to comment.