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 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. // Input asks for input to fill variables and provider configurations.
// This modifies the configuration in-place, so asking for Input twice // This modifies the configuration in-place, so asking for Input twice
// may result in different UI output showing different current values. // may result in different UI output showing different current values.

View File

@ -46,6 +46,10 @@ type InterpolationScope struct {
func (i *Interpolater) Values( func (i *Interpolater) Values(
scope *InterpolationScope, scope *InterpolationScope,
vars map[string]config.InterpolatedVariable) (map[string]ast.Variable, error) { vars map[string]config.InterpolatedVariable) (map[string]ast.Variable, error) {
if scope == nil {
scope = &InterpolationScope{}
}
result := make(map[string]ast.Variable, len(vars)) result := make(map[string]ast.Variable, len(vars))
// Copy the default variables // Copy the default variables
@ -369,7 +373,12 @@ func (i *Interpolater) computeResourceVariable(
// If we're requesting "count" its a special variable that we grab // If we're requesting "count" its a special variable that we grab
// directly from the config itself. // directly from the config itself.
if v.Field == "count" { 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 { if err != nil {
return nil, fmt.Errorf( return nil, fmt.Errorf(
"Error reading %s count: %s", "Error reading %s count: %s",
@ -380,26 +389,36 @@ func (i *Interpolater) computeResourceVariable(
return &ast.Variable{Type: ast.TypeInt, Value: count}, nil 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 // 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 // at this point and if there is a state, we expect there to be a
// resource with the given name. // resource with the given name.
r, ok := module.Resources[id] 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 { if !ok && v.Multi && v.Index == 0 {
r, ok = module.Resources[v.ResourceId()] r, ok = module.Resources[v.ResourceId()]
} }
if !ok { if !ok {
r = nil r = nil
} }
if r == nil { }
goto MISSING 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 goto MISSING
} }
@ -672,12 +691,6 @@ func (i *Interpolater) resourceVariableInfo(
break break
} }
} }
if cr == nil {
return nil, nil, fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
// Get the relevant module // Get the relevant module
module := i.State.ModuleByPath(scope.Path) module := i.State.ModuleByPath(scope.Path)