terraform: update interpolation to be more flexible w/o config

This commit is contained in:
Mitchell Hashimoto 2016-11-13 22:04:11 -08:00
parent 73a1564dac
commit 1a8fbdc428
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 50 additions and 22 deletions

View File

@ -229,6 +229,21 @@ func (c *Context) ShadowError() error {
return c.shadowErr
}
// Interpolater returns an Interpolater built on a copy of the state
// that can be used to test interpolation values.
func (c *Context) Interpolater() *Interpolater {
var varLock sync.Mutex
var stateLock sync.RWMutex
return &Interpolater{
Operation: walkApply,
Module: c.module,
State: c.state.DeepCopy(),
StateLock: &stateLock,
VariableValues: map[string]interface{}{},
VariableValuesLock: &varLock,
}
}
// Input asks for input to fill variables and provider configurations.
// This modifies the configuration in-place, so asking for Input twice
// may result in different UI output showing different current values.

View File

@ -46,6 +46,10 @@ type InterpolationScope struct {
func (i *Interpolater) Values(
scope *InterpolationScope,
vars map[string]config.InterpolatedVariable) (map[string]ast.Variable, error) {
if scope == nil {
scope = &InterpolationScope{}
}
result := make(map[string]ast.Variable, len(vars))
// Copy the default variables
@ -369,7 +373,12 @@ func (i *Interpolater) computeResourceVariable(
// If we're requesting "count" its a special variable that we grab
// directly from the config itself.
if v.Field == "count" {
count, err := cr.Count()
var count int
if cr != nil {
count, err = cr.Count()
} else {
count, err = i.resourceCountMax(module, cr, v)
}
if err != nil {
return nil, fmt.Errorf(
"Error reading %s count: %s",
@ -380,26 +389,36 @@ func (i *Interpolater) computeResourceVariable(
return &ast.Variable{Type: ast.TypeInt, Value: count}, nil
}
// If we have no module in the state yet or count, return empty
if module == nil || len(module.Resources) == 0 {
return nil, nil
}
// Get the resource out from the state. We know the state exists
// at this point and if there is a state, we expect there to be a
// resource with the given name.
r, ok := module.Resources[id]
if !ok && v.Multi && v.Index == 0 {
r, ok = module.Resources[v.ResourceId()]
}
if !ok {
r = nil
}
if r == nil {
goto MISSING
var r *ResourceState
if module != nil && len(module.Resources) > 0 {
var ok bool
r, ok = module.Resources[id]
if !ok && v.Multi && v.Index == 0 {
r, ok = module.Resources[v.ResourceId()]
}
if !ok {
r = nil
}
}
if r == nil || r.Primary == nil {
if i.Operation == walkApply || i.Operation == walkPlan {
return nil, fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
// If we have no module in the state yet or count, return empty.
// NOTE(@mitchellh): I actually don't know why this is here. During
// a refactor I kept this here to maintain the same behavior, but
// I'm not sure why its here.
if module == nil || len(module.Resources) == 0 {
return nil, nil
}
if r.Primary == nil {
goto MISSING
}
@ -672,12 +691,6 @@ func (i *Interpolater) resourceVariableInfo(
break
}
}
if cr == nil {
return nil, nil, fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
// Get the relevant module
module := i.State.ModuleByPath(scope.Path)