@@ -66,6 +66,14 @@ func (t *terraform) Provision(stream proto.DRPCProvisioner_ProvisionStream) erro
66
66
return xerrors .Errorf ("terraform version %q is too old. required >= %q" , version .String (), minimumTerraformVersion .String ())
67
67
}
68
68
69
+ statefilePath := filepath .Join (start .Directory , "terraform.tfstate" )
70
+ if len (start .State ) > 0 {
71
+ err := os .WriteFile (statefilePath , start .State , 0600 )
72
+ if err != nil {
73
+ return xerrors .Errorf ("write statefile %q: %w" , statefilePath , err )
74
+ }
75
+ }
76
+
69
77
reader , writer := io .Pipe ()
70
78
defer reader .Close ()
71
79
defer writer .Close ()
@@ -239,14 +247,7 @@ func (t *terraform) Provision(stream proto.DRPCProvisioner_ProvisionStream) erro
239
247
errorMessage := err .Error ()
240
248
// Terraform can fail and apply and still need to store it's state.
241
249
// In this case, we return Complete with an explicit error message.
242
- state , err := terraform .Show (stream .Context ())
243
- if err != nil {
244
- return xerrors .Errorf ("show state: %w" , err )
245
- }
246
- stateData , err := json .Marshal (state )
247
- if err != nil {
248
- return xerrors .Errorf ("marshal state: %w" , err )
249
- }
250
+ stateData , _ := os .ReadFile (statefilePath )
250
251
return stream .Send (& proto.Provision_Response {
251
252
Type : & proto.Provision_Response_Complete {
252
253
Complete : & proto.Provision_Complete {
@@ -263,7 +264,7 @@ func (t *terraform) Provision(stream proto.DRPCProvisioner_ProvisionStream) erro
263
264
if start .DryRun {
264
265
resp , err = parseTerraformPlan (stream .Context (), terraform , planfilePath )
265
266
} else {
266
- resp , err = parseTerraformApply (stream .Context (), terraform )
267
+ resp , err = parseTerraformApply (stream .Context (), terraform , statefilePath )
267
268
}
268
269
if err != nil {
269
270
return err
@@ -363,10 +364,26 @@ func parseTerraformPlan(ctx context.Context, terraform *tfexec.Terraform, planfi
363
364
}, nil
364
365
}
365
366
366
- func parseTerraformApply (ctx context.Context , terraform * tfexec.Terraform ) (* proto.Provision_Response , error ) {
367
- state , err := terraform .Show (ctx )
367
+ func parseTerraformApply (ctx context.Context , terraform * tfexec.Terraform , statefilePath string ) (* proto.Provision_Response , error ) {
368
+ _ , err := os .Stat (statefilePath )
369
+ statefileExisted := err == nil
370
+
371
+ statefile , err := os .OpenFile (statefilePath , os .O_CREATE | os .O_RDWR , 0600 )
368
372
if err != nil {
369
- return nil , xerrors .Errorf ("show state file: %w" , err )
373
+ return nil , xerrors .Errorf ("open statefile %q: %w" , statefilePath , err )
374
+ }
375
+ defer statefile .Close ()
376
+ // #nosec
377
+ cmd := exec .CommandContext (ctx , terraform .ExecPath (), "state" , "pull" )
378
+ cmd .Dir = terraform .WorkingDir ()
379
+ cmd .Stdout = statefile
380
+ err = cmd .Run ()
381
+ if err != nil {
382
+ return nil , xerrors .Errorf ("pull terraform state: %w" , err )
383
+ }
384
+ state , err := terraform .ShowStateFile (ctx , statefilePath )
385
+ if err != nil {
386
+ return nil , xerrors .Errorf ("show terraform state: %w" , err )
370
387
}
371
388
resources := make ([]* proto.Resource , 0 )
372
389
if state .Values != nil {
@@ -501,15 +518,19 @@ func parseTerraformApply(ctx context.Context, terraform *tfexec.Terraform) (*pro
501
518
}
502
519
}
503
520
504
- statefileContent , err := json .Marshal (state )
505
- if err != nil {
506
- return nil , xerrors .Errorf ("marshal state: %w" , err )
521
+ var stateContent []byte
522
+ // We only want to restore state if it's not hosted remotely.
523
+ if statefileExisted {
524
+ stateContent , err = os .ReadFile (statefilePath )
525
+ if err != nil {
526
+ return nil , xerrors .Errorf ("read statefile %q: %w" , statefilePath , err )
527
+ }
507
528
}
508
529
509
530
return & proto.Provision_Response {
510
531
Type : & proto.Provision_Response_Complete {
511
532
Complete : & proto.Provision_Complete {
512
- State : statefileContent ,
533
+ State : stateContent ,
513
534
Resources : resources ,
514
535
},
515
536
},
0 commit comments