config: validate backend configuration can't contain interpolations

This commit is contained in:
Mitchell Hashimoto 2017-02-17 16:25:03 -08:00
parent a2682bc94b
commit 6b4c007894
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
4 changed files with 70 additions and 21 deletions

View File

@ -9,7 +9,6 @@ import (
"strings" "strings"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hil" "github.com/hashicorp/hil"
"github.com/hashicorp/hil/ast" "github.com/hashicorp/hil/ast"
"github.com/hashicorp/terraform/helper/hilmapstructure" "github.com/hashicorp/terraform/helper/hilmapstructure"
@ -254,26 +253,7 @@ func (c *Config) Validate() error {
// Validate the Terraform config // Validate the Terraform config
if tf := c.Terraform; tf != nil { if tf := c.Terraform; tf != nil {
if raw := tf.RequiredVersion; raw != "" { errs = append(errs, c.Terraform.Validate()...)
// Check that the value has no interpolations
rc, err := NewRawConfig(map[string]interface{}{
"root": raw,
})
if err != nil {
errs = append(errs, fmt.Errorf(
"terraform.required_version: %s", err))
} else if len(rc.Interpolations) > 0 {
errs = append(errs, fmt.Errorf(
"terraform.required_version: cannot contain interpolations"))
} else {
// Check it is valid
_, err := version.NewConstraint(raw)
if err != nil {
errs = append(errs, fmt.Errorf(
"terraform.required_version: invalid syntax: %s", err))
}
}
}
} }
vars := c.InterpolatedVariables() vars := c.InterpolatedVariables()

View File

@ -1,6 +1,10 @@
package config package config
import ( import (
"fmt"
"strings"
"github.com/hashicorp/go-version"
"github.com/mitchellh/hashstructure" "github.com/mitchellh/hashstructure"
) )
@ -11,6 +15,38 @@ type Terraform struct {
Backend *Backend // See Backend struct docs Backend *Backend // See Backend struct docs
} }
// Validate performs the validation for just the Terraform configuration.
func (t *Terraform) Validate() []error {
var errs []error
if raw := t.RequiredVersion; raw != "" {
// Check that the value has no interpolations
rc, err := NewRawConfig(map[string]interface{}{
"root": raw,
})
if err != nil {
errs = append(errs, fmt.Errorf(
"terraform.required_version: %s", err))
} else if len(rc.Interpolations) > 0 {
errs = append(errs, fmt.Errorf(
"terraform.required_version: cannot contain interpolations"))
} else {
// Check it is valid
_, err := version.NewConstraint(raw)
if err != nil {
errs = append(errs, fmt.Errorf(
"terraform.required_version: invalid syntax: %s", err))
}
}
}
if t.Backend != nil {
errs = append(errs, t.Backend.Validate()...)
}
return errs
}
// Backend is the configuration for the "backend" to use with Terraform. // Backend is the configuration for the "backend" to use with Terraform.
// A backend is responsible for all major behavior of Terraform's core. // A backend is responsible for all major behavior of Terraform's core.
// The abstraction layer above the core (the "backend") allows for behavior // The abstraction layer above the core (the "backend") allows for behavior
@ -46,3 +82,24 @@ func (b *Backend) Rehash() uint64 {
return code return code
} }
func (b *Backend) Validate() []error {
if len(b.RawConfig.Interpolations) > 0 {
return []error{fmt.Errorf(strings.TrimSpace(errBackendInterpolations))}
}
return nil
}
const errBackendInterpolations = `
terraform.backend: configuration cannot contain interpolations
The backend configuration is loaded by Terraform extremely early, before
the core of Terraform can be initialized. This is necessary because the backend
dictates the behavior of that core. The core is what handles interpolation
processing. Because of this, interpolations cannot be used in backend
configuration.
If you'd like to parameterize backend configuration, we recommend using
partial configuration with the "-backend-config" flag to "terraform init".
`

View File

@ -194,6 +194,13 @@ func TestConfigValidate_table(t *testing.T) {
false, false,
"", "",
}, },
{
"backend config with interpolations",
"validate-backend-interpolate",
true,
"cannot contain interp",
},
} }
for i, tc := range cases { for i, tc := range cases {

View File

@ -0,0 +1,5 @@
terraform {
backend "foo" {
key = "${var.var}"
}
}