@@ -45,43 +45,59 @@ func newInputVariable(main *Main, addr stackaddrs.AbsInputVariable, stack *Stack
45
45
}
46
46
47
47
// DefinedByStackCallInstance returns the stack call which ought to provide
48
- // the definition (i.e. the final value) of this input variable.
48
+ // the definition (i.e. the final value) of this input variable. The source
49
+ // of the stack could either be a regular stack call instance or a removed
50
+ // stack call instance. One of the two will be returned. They are mutually
51
+ // exclusive as it is an error for two blocks to create the same stack instance.
49
52
//
50
53
// Returns nil if this input variable belongs to the main stack, because
51
54
// the main stack's input variables come from the planning options instead.
52
- // Also returns nil if the reciever belongs to a stack config instance
55
+ //
56
+ // Also returns nil if the receiver belongs to a stack config instance
53
57
// that isn't actually declared in the configuration, which typically suggests
54
58
// that we don't yet know the number of instances of one of the stack calls
55
59
// along the chain.
56
- func (v * InputVariable ) DefinedByStackCallInstance (ctx context.Context , phase EvalPhase ) * StackCallInstance {
60
+ func (v * InputVariable ) DefinedByStackCallInstance (ctx context.Context , phase EvalPhase ) ( * StackCallInstance , * RemovedStackCallInstance ) {
57
61
declarerAddr := v .addr .Stack
58
62
if declarerAddr .IsRoot () {
59
- return nil
63
+ return nil , nil
60
64
}
61
65
62
66
callAddr := declarerAddr .Call ()
63
- callerCalls := v .stack .parent .EmbeddedStackCalls ()
64
- call := callerCalls [callAddr .Item ]
65
- if call == nil {
66
- // Suggests that we're descended from a stack call that doesn't
67
- // actually exist, which is odd but we'll tolerate it.
68
- return nil
69
- }
70
67
71
- lastStep := declarerAddr [len (declarerAddr )- 1 ]
72
- instKey := lastStep .Key
68
+ if call := v .stack .parent .EmbeddedStackCall (callAddr .Item ); call != nil {
69
+ lastStep := declarerAddr [len (declarerAddr )- 1 ]
70
+ instKey := lastStep .Key
71
+
72
+ callInsts , unknown := call .Instances (ctx , phase )
73
+ if unknown {
74
+ // Return our static unknown instance for this variable.
75
+ return call .UnknownInstance (ctx , instKey , phase ), nil
76
+ }
77
+ if inst , ok := callInsts [instKey ]; ok {
78
+ return inst , nil
79
+ }
73
80
74
- callInsts , unknown := call .Instances (ctx , phase )
75
- if unknown {
76
- // Return our static unknown instance for this variable.
77
- return call .UnknownInstance (ctx , instKey , phase )
81
+ // otherwise, let's check if we have any removed calls that match the
82
+ // target instance
78
83
}
79
- if callInsts == nil {
80
- // Could get here if the call's for_each is invalid.
81
- return nil
84
+
85
+ if calls := v .stack .parent .RemovedEmbeddedStackCall (callAddr .Item ); calls != nil {
86
+ for _ , call := range calls {
87
+ callInsts , unknown := call .InstancesFor (ctx , v .stack .addr , phase )
88
+ if unknown {
89
+ return nil , call .UnknownInstance (ctx , v .stack .addr , phase )
90
+ }
91
+ for _ , inst := range callInsts {
92
+ // because we used the exact v.stack.addr in InstancesFor above
93
+ // then we should have at most one entry here if there were any
94
+ // matches.
95
+ return nil , inst
96
+ }
97
+ }
82
98
}
83
99
84
- return callInsts [ instKey ]
100
+ return nil , nil
85
101
}
86
102
87
103
func (v * InputVariable ) Value (ctx context.Context , phase EvalPhase ) cty.Value {
@@ -175,23 +191,32 @@ func (v *InputVariable) CheckValue(ctx context.Context, phase EvalPhase) (cty.Va
175
191
return cfg .markValue (val ), diags
176
192
177
193
default :
178
- definedByCallInst := v .DefinedByStackCallInstance (ctx , phase )
179
- if definedByCallInst == nil {
194
+ definedByCallInst , definedByRemovedCallInst := v .DefinedByStackCallInstance (ctx , phase )
195
+ switch {
196
+ case definedByCallInst != nil :
197
+ allVals := definedByCallInst .InputVariableValues (ctx , phase )
198
+ val := allVals .GetAttr (v .addr .Item .Name )
199
+
200
+ // TODO: check the value against any custom validation rules
201
+ // declared in the configuration.
202
+
203
+ return cfg .markValue (val ), diags
204
+ case definedByRemovedCallInst != nil :
205
+ allVals , _ := definedByRemovedCallInst .InputVariableValues (ctx , phase )
206
+ val := allVals .GetAttr (v .addr .Item .Name )
207
+
208
+ // TODO: check the value against any custom validation rules
209
+ // declared in the configuration.
210
+
211
+ return cfg .markValue (val ), diags
212
+ default :
180
213
// We seem to belong to a call instance that doesn't actually
181
214
// exist in the configuration. That either means that
182
215
// something's gone wrong or we are descended from a stack
183
216
// call whose instances aren't known yet; we'll assume
184
217
// the latter and return a placeholder.
185
218
return cfg .markValue (cty .UnknownVal (v .config .config .Type .Constraint )), diags
186
219
}
187
-
188
- allVals := definedByCallInst .InputVariableValues (ctx , phase )
189
- val := allVals .GetAttr (v .addr .Item .Name )
190
-
191
- // TODO: check the value against any custom validation rules
192
- // declared in the configuration.
193
-
194
- return cfg .markValue (val ), diags
195
220
}
196
221
},
197
222
)
0 commit comments