]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/eval_output.go
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / eval_output.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "fmt"
5 "log"
6
7 "github.com/hashicorp/terraform/config"
8)
9
10// EvalDeleteOutput is an EvalNode implementation that deletes an output
11// from the state.
12type EvalDeleteOutput struct {
13 Name string
14}
15
16// TODO: test
17func (n *EvalDeleteOutput) Eval(ctx EvalContext) (interface{}, error) {
18 state, lock := ctx.State()
19 if state == nil {
20 return nil, nil
21 }
22
23 // Get a write lock so we can access this instance
24 lock.Lock()
25 defer lock.Unlock()
26
27 // Look for the module state. If we don't have one, create it.
28 mod := state.ModuleByPath(ctx.Path())
29 if mod == nil {
30 return nil, nil
31 }
32
33 delete(mod.Outputs, n.Name)
34
35 return nil, nil
36}
37
38// EvalWriteOutput is an EvalNode implementation that writes the output
39// for the given name to the current state.
40type EvalWriteOutput struct {
41 Name string
42 Sensitive bool
43 Value *config.RawConfig
15c0b25d
AP
44 // ContinueOnErr allows interpolation to fail during Input
45 ContinueOnErr bool
bae9f6d2
JC
46}
47
48// TODO: test
49func (n *EvalWriteOutput) Eval(ctx EvalContext) (interface{}, error) {
15c0b25d
AP
50 // This has to run before we have a state lock, since interpolation also
51 // reads the state
bae9f6d2 52 cfg, err := ctx.Interpolate(n.Value, nil)
15c0b25d 53 // handle the error after we have the module from the state
bae9f6d2
JC
54
55 state, lock := ctx.State()
56 if state == nil {
57 return nil, fmt.Errorf("cannot write state to nil state")
58 }
59
60 // Get a write lock so we can access this instance
61 lock.Lock()
62 defer lock.Unlock()
bae9f6d2
JC
63 // Look for the module state. If we don't have one, create it.
64 mod := state.ModuleByPath(ctx.Path())
65 if mod == nil {
66 mod = state.AddModule(ctx.Path())
67 }
68
15c0b25d
AP
69 // handling the interpolation error
70 if err != nil {
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
74 // marked as unknown
75 mod.Outputs[n.Name] = &OutputState{
76 Type: "string",
77 Value: config.UnknownVariableValue,
78 }
79 return nil, EvalEarlyExitError{}
80 }
81 return nil, err
82 }
83
bae9f6d2
JC
84 // Get the value from the config
85 var valueRaw interface{} = config.UnknownVariableValue
86 if cfg != nil {
87 var ok bool
88 valueRaw, ok = cfg.Get("value")
89 if !ok {
90 valueRaw = ""
91 }
92 if cfg.IsComputed("value") {
93 valueRaw = config.UnknownVariableValue
94 }
95 }
96
97 switch valueTyped := valueRaw.(type) {
98 case string:
99 mod.Outputs[n.Name] = &OutputState{
100 Type: "string",
101 Sensitive: n.Sensitive,
102 Value: valueTyped,
103 }
104 case []interface{}:
105 mod.Outputs[n.Name] = &OutputState{
106 Type: "list",
107 Sensitive: n.Sensitive,
108 Value: valueTyped,
109 }
110 case map[string]interface{}:
111 mod.Outputs[n.Name] = &OutputState{
112 Type: "map",
113 Sensitive: n.Sensitive,
114 Value: valueTyped,
115 }
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{
121 Type: "map",
122 Sensitive: n.Sensitive,
123 Value: valueTyped[0],
124 }
125 break
126 }
127 return nil, fmt.Errorf("output %s type (%T) with %d values not valid for type map",
128 n.Name, valueTyped, len(valueTyped))
129 default:
130 return nil, fmt.Errorf("output %s is not a valid type (%T)\n", n.Name, valueTyped)
131 }
132
133 return nil, nil
134}