]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | ||
6 | "github.com/hashicorp/terraform/config" | |
7 | ) | |
8 | ||
9 | // EvalSetProviderConfig sets the parent configuration for a provider | |
10 | // without configuring that provider, validating it, etc. | |
11 | type EvalSetProviderConfig struct { | |
12 | Provider string | |
13 | Config **ResourceConfig | |
14 | } | |
15 | ||
16 | func (n *EvalSetProviderConfig) Eval(ctx EvalContext) (interface{}, error) { | |
17 | return nil, ctx.SetProviderConfig(n.Provider, *n.Config) | |
18 | } | |
19 | ||
20 | // EvalBuildProviderConfig outputs a *ResourceConfig that is properly | |
21 | // merged with parents and inputs on top of what is configured in the file. | |
22 | type EvalBuildProviderConfig struct { | |
23 | Provider string | |
24 | Config **ResourceConfig | |
25 | Output **ResourceConfig | |
26 | } | |
27 | ||
28 | func (n *EvalBuildProviderConfig) Eval(ctx EvalContext) (interface{}, error) { | |
29 | cfg := *n.Config | |
30 | ||
31 | // If we have a configuration set, then merge that in | |
32 | if input := ctx.ProviderInput(n.Provider); input != nil { | |
33 | // "input" is a map of the subset of config values that were known | |
34 | // during the input walk, set by EvalInputProvider. Note that | |
35 | // in particular it does *not* include attributes that had | |
36 | // computed values at input time; those appear *only* in | |
37 | // "cfg" here. | |
38 | rc, err := config.NewRawConfig(input) | |
39 | if err != nil { | |
40 | return nil, err | |
41 | } | |
42 | ||
43 | merged := cfg.raw.Merge(rc) | |
44 | cfg = NewResourceConfig(merged) | |
45 | } | |
46 | ||
47 | // Get the parent configuration if there is one | |
48 | if parent := ctx.ParentProviderConfig(n.Provider); parent != nil { | |
49 | merged := cfg.raw.Merge(parent.raw) | |
50 | cfg = NewResourceConfig(merged) | |
51 | } | |
52 | ||
53 | *n.Output = cfg | |
54 | return nil, nil | |
55 | } | |
56 | ||
57 | // EvalConfigProvider is an EvalNode implementation that configures | |
58 | // a provider that is already initialized and retrieved. | |
59 | type EvalConfigProvider struct { | |
60 | Provider string | |
61 | Config **ResourceConfig | |
62 | } | |
63 | ||
64 | func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { | |
65 | return nil, ctx.ConfigureProvider(n.Provider, *n.Config) | |
66 | } | |
67 | ||
68 | // EvalInitProvider is an EvalNode implementation that initializes a provider | |
69 | // and returns nothing. The provider can be retrieved again with the | |
70 | // EvalGetProvider node. | |
71 | type EvalInitProvider struct { | |
72 | Name string | |
73 | } | |
74 | ||
75 | func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) { | |
76 | return ctx.InitProvider(n.Name) | |
77 | } | |
78 | ||
79 | // EvalCloseProvider is an EvalNode implementation that closes provider | |
80 | // connections that aren't needed anymore. | |
81 | type EvalCloseProvider struct { | |
82 | Name string | |
83 | } | |
84 | ||
85 | func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) { | |
86 | ctx.CloseProvider(n.Name) | |
87 | return nil, nil | |
88 | } | |
89 | ||
90 | // EvalGetProvider is an EvalNode implementation that retrieves an already | |
91 | // initialized provider instance for the given name. | |
92 | type EvalGetProvider struct { | |
93 | Name string | |
94 | Output *ResourceProvider | |
95 | } | |
96 | ||
97 | func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { | |
98 | result := ctx.Provider(n.Name) | |
99 | if result == nil { | |
100 | return nil, fmt.Errorf("provider %s not initialized", n.Name) | |
101 | } | |
102 | ||
103 | if n.Output != nil { | |
104 | *n.Output = result | |
105 | } | |
106 | ||
107 | return nil, nil | |
108 | } | |
109 | ||
110 | // EvalInputProvider is an EvalNode implementation that asks for input | |
111 | // for the given provider configurations. | |
112 | type EvalInputProvider struct { | |
113 | Name string | |
114 | Provider *ResourceProvider | |
115 | Config **ResourceConfig | |
116 | } | |
117 | ||
118 | func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) { | |
119 | // If we already configured this provider, then don't do this again | |
120 | if v := ctx.ProviderInput(n.Name); v != nil { | |
121 | return nil, nil | |
122 | } | |
123 | ||
124 | rc := *n.Config | |
125 | ||
126 | // Wrap the input into a namespace | |
127 | input := &PrefixUIInput{ | |
128 | IdPrefix: fmt.Sprintf("provider.%s", n.Name), | |
129 | QueryPrefix: fmt.Sprintf("provider.%s.", n.Name), | |
130 | UIInput: ctx.Input(), | |
131 | } | |
132 | ||
133 | // Go through each provider and capture the input necessary | |
134 | // to satisfy it. | |
135 | config, err := (*n.Provider).Input(input, rc) | |
136 | if err != nil { | |
137 | return nil, fmt.Errorf( | |
138 | "Error configuring %s: %s", n.Name, err) | |
139 | } | |
140 | ||
141 | // Set the input that we received so that child modules don't attempt | |
142 | // to ask for input again. | |
143 | if config != nil && len(config.Config) > 0 { | |
144 | // This repository of provider input results on the context doesn't | |
145 | // retain config.ComputedKeys, so we need to filter those out here | |
146 | // in order that later users of this data won't try to use the unknown | |
147 | // value placeholder as if it were a literal value. This map is just | |
148 | // of known values we've been able to complete so far; dynamic stuff | |
149 | // will be merged in by EvalBuildProviderConfig on subsequent | |
150 | // (post-input) walks. | |
151 | confMap := config.Config | |
152 | if config.ComputedKeys != nil { | |
153 | for _, key := range config.ComputedKeys { | |
154 | delete(confMap, key) | |
155 | } | |
156 | } | |
157 | ||
158 | ctx.SetProviderInput(n.Name, confMap) | |
159 | } else { | |
160 | ctx.SetProviderInput(n.Name, map[string]interface{}{}) | |
161 | } | |
162 | ||
163 | return nil, nil | |
164 | } |