core: don't crash when count.index is used in the wrong context

It's bad manners! :)

Also adds a validation error up at the configuration layer so the user
sees the case from #1528 as an error message.

fixes #1528
This commit is contained in:
Paul Hinze 2015-04-14 19:42:23 -05:00
parent 062947556a
commit 347690a73e
5 changed files with 52 additions and 0 deletions

View File

@ -472,6 +472,13 @@ func (c *Config) Validate() error {
errs = append(errs, fmt.Errorf(
"%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

View File

@ -3,6 +3,7 @@ package config
import (
"path/filepath"
"reflect"
"strings"
"testing"
)
@ -60,6 +61,15 @@ func TestConfigValidate_countInt(t *testing.T) {
}
}
func TestConfigValidate_countBadContext(t *testing.T) {
c := testConfig(t, "validate-count-bad-context")
expected := "count variables are only valid within resources"
err := c.Validate()
if !strings.Contains(err.Error(), expected) {
t.Fatalf("expected: %q,\nto contain: %q", err, expected)
}
}
func TestConfigValidate_countCountVar(t *testing.T) {
c := testConfig(t, "validate-count-count-var")
if err := c.Validate(); err == nil {

View File

@ -0,0 +1,6 @@
resource "aws_instance" "foo" {
}
output "notgood" {
value = "${count.index}"
}

View File

@ -85,6 +85,9 @@ func (i *Interpolater) valueCountVar(
result map[string]ast.Variable) error {
switch v.Type {
case config.CountValueIndex:
if scope.Resource == nil {
return fmt.Errorf("%s: count.index is only valid within resources", n)
}
result[n] = ast.Variable{
Value: scope.Resource.CountIndex,
Type: ast.TypeInt,

View File

@ -1,6 +1,7 @@
package terraform
import (
"fmt"
"os"
"reflect"
"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) {
lock := new(sync.RWMutex)
state := &State{