2015-02-11 10:48:45 -06:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
|
|
|
// EvalReadState is an EvalNode implementation that reads the
|
|
|
|
// InstanceState for a specific resource out of the state.
|
|
|
|
type EvalReadState struct {
|
2015-02-11 16:14:05 -06:00
|
|
|
Name string
|
|
|
|
Tainted bool
|
|
|
|
TaintedIndex int
|
2015-02-12 16:46:22 -06:00
|
|
|
Output **InstanceState
|
2015-02-11 10:48:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: test
|
2015-02-14 00:58:41 -06:00
|
|
|
func (n *EvalReadState) Eval(ctx EvalContext) (interface{}, error) {
|
2015-02-11 10:48:45 -06:00
|
|
|
state, lock := ctx.State()
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2015-02-12 16:46:22 -06:00
|
|
|
var result *InstanceState
|
2015-02-11 16:14:05 -06:00
|
|
|
if !n.Tainted {
|
|
|
|
// Return the primary
|
2015-02-12 16:46:22 -06:00
|
|
|
result = rs.Primary
|
2015-02-11 16:14:05 -06:00
|
|
|
} else {
|
2015-02-13 18:27:23 -06:00
|
|
|
// 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 < len(rs.Tainted) {
|
|
|
|
// Return the proper tainted resource
|
|
|
|
result = rs.Tainted[n.TaintedIndex]
|
|
|
|
}
|
2015-02-11 16:14:05 -06:00
|
|
|
}
|
2015-02-12 16:46:22 -06:00
|
|
|
|
|
|
|
// Write the result to the output pointer
|
|
|
|
if n.Output != nil {
|
|
|
|
*n.Output = result
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
2015-02-11 10:48:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// EvalWriteState is an EvalNode implementation that reads the
|
|
|
|
// InstanceState for a specific resource out of the state.
|
|
|
|
type EvalWriteState struct {
|
2015-02-13 11:49:29 -06:00
|
|
|
Name string
|
|
|
|
ResourceType string
|
|
|
|
Dependencies []string
|
|
|
|
State **InstanceState
|
|
|
|
Tainted *bool
|
|
|
|
TaintedIndex int
|
|
|
|
TaintedClearPrimary bool
|
2015-02-11 10:48:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: test
|
2015-02-14 00:58:41 -06:00
|
|
|
func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
2015-02-11 10:48:45 -06:00
|
|
|
state, lock := ctx.State()
|
|
|
|
if state == nil {
|
|
|
|
return nil, fmt.Errorf("cannot write state to nil state")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a write lock so we can access this instance
|
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
|
|
|
|
// Look for the module state. If we don't have one, create it.
|
|
|
|
mod := state.ModuleByPath(ctx.Path())
|
|
|
|
if mod == nil {
|
|
|
|
mod = state.AddModule(ctx.Path())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for the resource state.
|
|
|
|
rs := mod.Resources[n.Name]
|
|
|
|
if rs == nil {
|
|
|
|
rs = &ResourceState{}
|
|
|
|
rs.init()
|
|
|
|
mod.Resources[n.Name] = rs
|
|
|
|
}
|
|
|
|
rs.Type = n.ResourceType
|
|
|
|
rs.Dependencies = n.Dependencies
|
|
|
|
|
2015-02-13 11:49:29 -06:00
|
|
|
if n.Tainted != nil && *n.Tainted {
|
2015-02-11 16:14:05 -06:00
|
|
|
if n.TaintedIndex != -1 {
|
2015-02-12 16:46:22 -06:00
|
|
|
rs.Tainted[n.TaintedIndex] = *n.State
|
2015-02-13 11:49:29 -06:00
|
|
|
} else {
|
|
|
|
rs.Tainted = append(rs.Tainted, *n.State)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n.TaintedClearPrimary {
|
|
|
|
rs.Primary = nil
|
2015-02-11 16:14:05 -06:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Set the primary state
|
2015-02-12 16:46:22 -06:00
|
|
|
rs.Primary = *n.State
|
2015-02-11 16:14:05 -06:00
|
|
|
}
|
2015-02-13 18:27:23 -06:00
|
|
|
println(fmt.Sprintf("%#v", rs))
|
2015-02-11 10:48:45 -06:00
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-02-13 18:44:50 -06:00
|
|
|
// EvalDeposeState is an EvalNode implementation that takes the primary
|
|
|
|
// out of a state and makes it tainted. This is done at the beggining of
|
|
|
|
// create-before-destroy calls so that the create can create while preserving
|
|
|
|
// the old state of the to-be-destroyed resource.
|
2015-02-13 17:57:37 -06:00
|
|
|
type EvalDeposeState struct {
|
|
|
|
Name string
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: test
|
2015-02-14 00:58:41 -06:00
|
|
|
func (n *EvalDeposeState) Eval(ctx EvalContext) (interface{}, error) {
|
2015-02-13 17:57:37 -06:00
|
|
|
state, lock := ctx.State()
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't have a primary, we have nothing to depose
|
|
|
|
if rs.Primary == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Depose to the tainted
|
|
|
|
rs.Tainted = append(rs.Tainted, rs.Primary)
|
|
|
|
rs.Primary = nil
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// EvalUndeposeState is an EvalNode implementation that reads the
|
|
|
|
// InstanceState for a specific resource out of the state.
|
|
|
|
type EvalUndeposeState struct {
|
|
|
|
Name string
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: test
|
2015-02-14 00:58:41 -06:00
|
|
|
func (n *EvalUndeposeState) Eval(ctx EvalContext) (interface{}, error) {
|
2015-02-13 17:57:37 -06:00
|
|
|
state, lock := ctx.State()
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't have any tainted, then we don't have anything to do
|
|
|
|
if len(rs.Tainted) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Undepose to the tainted
|
|
|
|
idx := len(rs.Tainted) - 1
|
|
|
|
rs.Primary = rs.Tainted[idx]
|
|
|
|
rs.Tainted[idx] = nil
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|