7 "github.com/hashicorp/terraform/config"
10 // EvalDeleteOutput is an EvalNode implementation that deletes an output
12 type EvalDeleteOutput struct {
17 func (n *EvalDeleteOutput) Eval(ctx EvalContext) (interface{}, error) {
18 state, lock := ctx.State()
23 // Get a write lock so we can access this instance
27 // Look for the module state. If we don't have one, create it.
28 mod := state.ModuleByPath(ctx.Path())
33 delete(mod.Outputs, n.Name)
38 // EvalWriteOutput is an EvalNode implementation that writes the output
39 // for the given name to the current state.
40 type EvalWriteOutput struct {
43 Value *config.RawConfig
44 // ContinueOnErr allows interpolation to fail during Input
49 func (n *EvalWriteOutput) Eval(ctx EvalContext) (interface{}, error) {
50 // This has to run before we have a state lock, since interpolation also
52 cfg, err := ctx.Interpolate(n.Value, nil)
53 // handle the error after we have the module from the state
55 state, lock := ctx.State()
57 return nil, fmt.Errorf("cannot write state to nil state")
60 // Get a write lock so we can access this instance
63 // Look for the module state. If we don't have one, create it.
64 mod := state.ModuleByPath(ctx.Path())
66 mod = state.AddModule(ctx.Path())
69 // handling the interpolation error
71 if n.ContinueOnErr || flagWarnOutputErrors {
72 log.Printf("[ERROR] Output interpolation %q failed: %s", n.Name, err)
73 // if we're continuing, make sure the output is included, and
75 mod.Outputs[n.Name] = &OutputState{
77 Value: config.UnknownVariableValue,
79 return nil, EvalEarlyExitError{}
84 // Get the value from the config
85 var valueRaw interface{} = config.UnknownVariableValue
88 valueRaw, ok = cfg.Get("value")
92 if cfg.IsComputed("value") {
93 valueRaw = config.UnknownVariableValue
97 switch valueTyped := valueRaw.(type) {
99 mod.Outputs[n.Name] = &OutputState{
101 Sensitive: n.Sensitive,
105 mod.Outputs[n.Name] = &OutputState{
107 Sensitive: n.Sensitive,
110 case map[string]interface{}:
111 mod.Outputs[n.Name] = &OutputState{
113 Sensitive: n.Sensitive,
116 case []map[string]interface{}:
117 // an HCL map is multi-valued, so if this was read out of a config the
118 // map may still be in a slice.
119 if len(valueTyped) == 1 {
120 mod.Outputs[n.Name] = &OutputState{
122 Sensitive: n.Sensitive,
123 Value: valueTyped[0],
127 return nil, fmt.Errorf("output %s type (%T) with %d values not valid for type map",
128 n.Name, valueTyped, len(valueTyped))
130 return nil, fmt.Errorf("output %s is not a valid type (%T)\n", n.Name, valueTyped)