Merge pull request #1534 from hashicorp/b-crash-on-output-interpolate
core: don't crash when count.index is used in the wrong context
This commit is contained in:
commit
43231b56d2
|
@ -290,6 +290,14 @@ func (c *Config) Validate() error {
|
||||||
raw[k] = strVal
|
raw[k] = strVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for invalid count variables
|
||||||
|
for _, v := range m.RawConfig.Variables {
|
||||||
|
if _, ok := v.(*CountVariable); ok {
|
||||||
|
errs = append(errs, fmt.Errorf(
|
||||||
|
"%s: count variables are only valid within resources", m.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the raw configuration to only contain the string values
|
// Update the raw configuration to only contain the string values
|
||||||
m.RawConfig, err = NewRawConfig(raw)
|
m.RawConfig, err = NewRawConfig(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -472,6 +480,13 @@ func (c *Config) Validate() error {
|
||||||
errs = append(errs, fmt.Errorf(
|
errs = append(errs, fmt.Errorf(
|
||||||
"%s: output should only have 'value' field", o.Name))
|
"%s: output should only have 'value' field", o.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, v := range o.RawConfig.Variables {
|
||||||
|
if _, ok := v.(*CountVariable); ok {
|
||||||
|
errs = append(errs, fmt.Errorf(
|
||||||
|
"%s: count variables are only valid within resources", o.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that all variables are in the proper context
|
// Check that all variables are in the proper context
|
||||||
|
|
|
@ -3,6 +3,7 @@ package config
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,6 +61,22 @@ func TestConfigValidate_countInt(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigValidate_countBadContext(t *testing.T) {
|
||||||
|
c := testConfig(t, "validate-count-bad-context")
|
||||||
|
|
||||||
|
err := c.Validate()
|
||||||
|
|
||||||
|
expected := []string{
|
||||||
|
"no_count_in_output: count variables are only valid within resources",
|
||||||
|
"no_count_in_module: count variables are only valid within resources",
|
||||||
|
}
|
||||||
|
for _, exp := range expected {
|
||||||
|
if !strings.Contains(err.Error(), exp) {
|
||||||
|
t.Fatalf("expected: %q,\nto contain: %q", err, exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfigValidate_countCountVar(t *testing.T) {
|
func TestConfigValidate_countCountVar(t *testing.T) {
|
||||||
c := testConfig(t, "validate-count-count-var")
|
c := testConfig(t, "validate-count-count-var")
|
||||||
if err := c.Validate(); err == nil {
|
if err := c.Validate(); err == nil {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
resource "aws_instance" "foo" {
|
||||||
|
}
|
||||||
|
|
||||||
|
output "no_count_in_output" {
|
||||||
|
value = "${count.index}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "no_count_in_module" {
|
||||||
|
source = "./child"
|
||||||
|
somevar = "${count.index}"
|
||||||
|
}
|
|
@ -85,6 +85,9 @@ func (i *Interpolater) valueCountVar(
|
||||||
result map[string]ast.Variable) error {
|
result map[string]ast.Variable) error {
|
||||||
switch v.Type {
|
switch v.Type {
|
||||||
case config.CountValueIndex:
|
case config.CountValueIndex:
|
||||||
|
if scope.Resource == nil {
|
||||||
|
return fmt.Errorf("%s: count.index is only valid within resources", n)
|
||||||
|
}
|
||||||
result[n] = ast.Variable{
|
result[n] = ast.Variable{
|
||||||
Value: scope.Resource.CountIndex,
|
Value: scope.Resource.CountIndex,
|
||||||
Type: ast.TypeInt,
|
Type: ast.TypeInt,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -24,6 +25,31 @@ func TestInterpolater_countIndex(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInterpolater_countIndexInWrongContext(t *testing.T) {
|
||||||
|
i := &Interpolater{}
|
||||||
|
|
||||||
|
scope := &InterpolationScope{
|
||||||
|
Path: rootModulePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
n := "count.index"
|
||||||
|
|
||||||
|
v, err := config.NewInterpolatedVariable(n)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedErr := fmt.Errorf("foo: count.index is only valid within resources")
|
||||||
|
|
||||||
|
_, err = i.Values(scope, map[string]config.InterpolatedVariable{
|
||||||
|
"foo": v,
|
||||||
|
})
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expectedErr, err) {
|
||||||
|
t.Fatalf("expected: %#v, got %#v", expectedErr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInterpolater_moduleVariable(t *testing.T) {
|
func TestInterpolater_moduleVariable(t *testing.T) {
|
||||||
lock := new(sync.RWMutex)
|
lock := new(sync.RWMutex)
|
||||||
state := &State{
|
state := &State{
|
||||||
|
|
Loading…
Reference in New Issue