@@ -13,6 +13,7 @@ import (
13
13
"strings"
14
14
15
15
"github.com/hashicorp/terraform-exec/tfexec"
16
+ tfjson "github.com/hashicorp/terraform-json"
16
17
"github.com/mitchellh/mapstructure"
17
18
"golang.org/x/xerrors"
18
19
@@ -75,10 +76,13 @@ func (t *terraform) Provision(request *proto.Provision_Request, stream proto.DRP
75
76
}
76
77
77
78
func (t * terraform ) runTerraformPlan (ctx context.Context , terraform * tfexec.Terraform , request * proto.Provision_Request , stream proto.DRPCProvisioner_ProvisionStream ) error {
78
- env := map [string ]string {
79
- "CODER_URL" : request .Metadata .CoderUrl ,
80
- "CODER_WORKSPACE_TRANSITION" : strings .ToLower (request .Metadata .WorkspaceTransition .String ()),
79
+ env := map [string ]string {}
80
+ for _ , envEntry := range os .Environ () {
81
+ parts := strings .SplitN (envEntry , "=" , 2 )
82
+ env [parts [0 ]] = parts [1 ]
81
83
}
84
+ env ["CODER_URL" ] = request .Metadata .CoderUrl
85
+ env ["CODER_WORKSPACE_TRANSITION" ] = strings .ToLower (request .Metadata .WorkspaceTransition .String ())
82
86
planfilePath := filepath .Join (request .Directory , "terraform.tfplan" )
83
87
options := []tfexec.PlanOption {tfexec .JSON (true ), tfexec .Out (planfilePath )}
84
88
for _ , param := range request .ParameterValues {
@@ -159,9 +163,31 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr
159
163
_ = reader .Close ()
160
164
<- closeChan
161
165
166
+ // Maps resource dependencies to expression references.
167
+ // This is *required* for a plan, because "DependsOn"
168
+ // does not propagate.
169
+ resourceDependencies := map [string ][]string {}
170
+ for _ , resource := range plan .Config .RootModule .Resources {
171
+ if resource .Expressions == nil {
172
+ resource .Expressions = map [string ]* tfjson.Expression {}
173
+ }
174
+ // Count expression is separated for logical reasons,
175
+ // but it's simpler syntactically for us to combine here.
176
+ if resource .CountExpression != nil {
177
+ resource .Expressions ["count" ] = resource .CountExpression
178
+ }
179
+ for _ , expression := range resource .Expressions {
180
+ dependencies , exists := resourceDependencies [resource .Address ]
181
+ if ! exists {
182
+ dependencies = []string {}
183
+ }
184
+ dependencies = append (dependencies , expression .References ... )
185
+ resourceDependencies [resource .Address ] = dependencies
186
+ }
187
+ }
188
+
162
189
resources := make ([]* proto.Resource , 0 )
163
190
agents := map [string ]* proto.Agent {}
164
- agentDepends := map [string ][]string {}
165
191
166
192
// Store all agents inside the maps!
167
193
for _ , resource := range plan .Config .RootModule .Resources {
@@ -209,31 +235,33 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr
209
235
}
210
236
}
211
237
212
- resourceKey := strings .Join ([]string {resource .Type , resource .Name }, "." )
213
- agents [resourceKey ] = agent
214
- agentDepends [resourceKey ] = resource .DependsOn
238
+ agents [resource .Address ] = agent
215
239
}
216
240
217
- for _ , resource := range plan .Config .RootModule .Resources {
241
+ for _ , resource := range plan .PlannedValues .RootModule .Resources {
218
242
if resource .Type == "coder_agent" {
219
243
continue
220
244
}
245
+ // The resource address on planned values can include the indexed
246
+ // value like "[0]", but the config doesn't have these, and we don't
247
+ // care which index the resource is.
248
+ resourceAddress := fmt .Sprintf ("%s.%s" , resource .Type , resource .Name )
221
249
var agent * proto.Agent
222
250
// Associate resources that depend on an agent.
223
- for _ , dep := range resource . DependsOn {
251
+ for _ , dependency := range resourceDependencies [ resourceAddress ] {
224
252
var has bool
225
- agent , has = agents [dep ]
253
+ agent , has = agents [dependency ]
226
254
if has {
227
255
break
228
256
}
229
257
}
230
258
// Associate resources where the agent depends on it.
231
- for agentKey , dependsOn := range agentDepends {
232
- for _ , depend := range dependsOn {
233
- if depend != strings . Join ([] string { resource .Type , resource . Name }, "." ) {
259
+ for agentAddress := range agents {
260
+ for _ , depend := range resourceDependencies [ agentAddress ] {
261
+ if depend != resource .Address {
234
262
continue
235
263
}
236
- agent = agents [agentKey ]
264
+ agent = agents [agentAddress ]
237
265
break
238
266
}
239
267
}
@@ -255,10 +283,11 @@ func (t *terraform) runTerraformPlan(ctx context.Context, terraform *tfexec.Terr
255
283
}
256
284
257
285
func (t * terraform ) runTerraformApply (ctx context.Context , terraform * tfexec.Terraform , request * proto.Provision_Request , stream proto.DRPCProvisioner_ProvisionStream , statefilePath string ) error {
258
- env := []string {
259
- "CODER_URL=" + request .Metadata .CoderUrl ,
260
- "CODER_WORKSPACE_TRANSITION=" + strings .ToLower (request .Metadata .WorkspaceTransition .String ()),
261
- }
286
+ env := os .Environ ()
287
+ env = append (env ,
288
+ "CODER_URL=" + request .Metadata .CoderUrl ,
289
+ "CODER_WORKSPACE_TRANSITION=" + strings .ToLower (request .Metadata .WorkspaceTransition .String ()),
290
+ )
262
291
vars := []string {}
263
292
for _ , param := range request .ParameterValues {
264
293
switch param .DestinationScheme {
0 commit comments