core: [refactor] pull out common ReadState behavior

This commit is contained in:
Paul Hinze 2015-03-02 13:05:38 -06:00
parent 596e891b80
commit d81ec2d37e
1 changed files with 41 additions and 68 deletions

View File

@ -5,41 +5,20 @@ import (
) )
// EvalReadState is an EvalNode implementation that reads the // EvalReadState is an EvalNode implementation that reads the
// InstanceState for a specific resource out of the state. // primary InstanceState for a specific resource out of the state.
type EvalReadState struct { type EvalReadState struct {
Name string Name string
Output **InstanceState Output **InstanceState
} }
func (n *EvalReadState) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalReadState) Eval(ctx EvalContext) (interface{}, error) {
state, lock := ctx.State() return readInstanceFromState(ctx, n.Name, n.Output, func(rs *ResourceState) (*InstanceState, error) {
return rs.Primary, nil
// Get a read lock so we can access this instance })
lock.RLock()
defer lock.RUnlock()
// Look for the module state. If we don't have one, then it doesn't matter.
mod := state.ModuleByPath(ctx.Path())
if mod == nil {
return nil, nil
}
// Look for the resource state. If we don't have one, then it is okay.
rs := mod.Resources[n.Name]
if rs == nil {
return nil, nil
}
// Write the result to the output pointer
if n.Output != nil {
*n.Output = rs.Primary
}
return rs.Primary, nil
} }
// EvalReadStateTainted is an EvalNode implementation that reads the // EvalReadStateTainted is an EvalNode implementation that reads a
// InstanceState for a specific tainted resource out of the state // tainted InstanceState for a specific resource out of the state
type EvalReadStateTainted struct { type EvalReadStateTainted struct {
Name string Name string
Output **InstanceState Output **InstanceState
@ -50,51 +29,39 @@ type EvalReadStateTainted struct {
} }
func (n *EvalReadStateTainted) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalReadStateTainted) Eval(ctx EvalContext) (interface{}, error) {
state, lock := ctx.State() return readInstanceFromState(ctx, n.Name, n.Output, func(rs *ResourceState) (*InstanceState, error) {
// Get the index. If it is negative, then we get the last one
// Get a read lock so we can access this instance idx := n.TaintedIndex
lock.RLock() if idx < 0 {
defer lock.RUnlock() idx = len(rs.Tainted) - 1
}
// Look for the module state. If we don't have one, then it doesn't matter. if idx >= 0 && idx < len(rs.Tainted) {
mod := state.ModuleByPath(ctx.Path()) return rs.Tainted[idx], nil
if mod == nil { } else {
return nil, nil return nil, fmt.Errorf("bad tainted index: %d, for resource: %#v", idx, rs)
} }
})
// Look for the resource state. If we don't have one, then it is okay.
rs := mod.Resources[n.Name]
if rs == nil {
return nil, nil
}
var result *InstanceState
// Get the index. If it is negative, then we get the last one
idx := n.TaintedIndex
if idx < 0 {
idx = len(rs.Tainted) - 1
}
if idx >= 0 && idx < len(rs.Tainted) {
// Return the proper tainted resource
result = rs.Tainted[idx]
}
// Write the result to the output pointer
if n.Output != nil {
*n.Output = result
}
return result, nil
} }
// EvalReadStateDeposed is an EvalNode implementation that reads the // EvalReadStateDeposed is an EvalNode implementation that reads the
// InstanceState for a specific deposed resource out of the state // deposed InstanceState for a specific resource out of the state
type EvalReadStateDeposed struct { type EvalReadStateDeposed struct {
Name string Name string
Output **InstanceState Output **InstanceState
} }
func (n *EvalReadStateDeposed) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalReadStateDeposed) Eval(ctx EvalContext) (interface{}, error) {
return readInstanceFromState(ctx, n.Name, n.Output, func(rs *ResourceState) (*InstanceState, error) {
return rs.Deposed, nil
})
}
func readInstanceFromState(
ctx EvalContext,
resourceName string,
output **InstanceState,
f func(*ResourceState) (*InstanceState, error),
) (*InstanceState, error) {
state, lock := ctx.State() state, lock := ctx.State()
// Get a read lock so we can access this instance // Get a read lock so we can access this instance
@ -108,17 +75,23 @@ func (n *EvalReadStateDeposed) Eval(ctx EvalContext) (interface{}, error) {
} }
// Look for the resource state. If we don't have one, then it is okay. // Look for the resource state. If we don't have one, then it is okay.
rs := mod.Resources[n.Name] rs := mod.Resources[resourceName]
if rs == nil { if rs == nil {
return nil, nil return nil, nil
} }
// Write the result to the output pointer // Use the delegate function to get the instance state from the resource state
if n.Output != nil { is, err := f(rs)
*n.Output = rs.Deposed if err != nil {
return nil, err
} }
return rs.Deposed, nil // Write the result to the output pointer
if output != nil {
*output = is
}
return is, nil
} }
// EvalRequireState is an EvalNode implementation that early exits // EvalRequireState is an EvalNode implementation that early exits