1package planfile 2 3import ( 4 "archive/zip" 5 "fmt" 6 "os" 7 "time" 8 9 "github.com/hashicorp/terraform/internal/configs/configload" 10 "github.com/hashicorp/terraform/internal/plans" 11 "github.com/hashicorp/terraform/internal/states/statefile" 12) 13 14// Create creates a new plan file with the given filename, overwriting any 15// file that might already exist there. 16// 17// A plan file contains both a snapshot of the configuration and of the latest 18// state file in addition to the plan itself, so that Terraform can detect 19// if the world has changed since the plan was created and thus refuse to 20// apply it. 21func Create(filename string, configSnap *configload.Snapshot, prevStateFile, stateFile *statefile.File, plan *plans.Plan) error { 22 f, err := os.Create(filename) 23 if err != nil { 24 return err 25 } 26 defer f.Close() 27 28 zw := zip.NewWriter(f) 29 defer zw.Close() 30 31 // tfplan file 32 { 33 w, err := zw.CreateHeader(&zip.FileHeader{ 34 Name: tfplanFilename, 35 Method: zip.Deflate, 36 Modified: time.Now(), 37 }) 38 if err != nil { 39 return fmt.Errorf("failed to create tfplan file: %s", err) 40 } 41 err = writeTfplan(plan, w) 42 if err != nil { 43 return fmt.Errorf("failed to write plan: %s", err) 44 } 45 } 46 47 // tfstate file 48 { 49 w, err := zw.CreateHeader(&zip.FileHeader{ 50 Name: tfstateFilename, 51 Method: zip.Deflate, 52 Modified: time.Now(), 53 }) 54 if err != nil { 55 return fmt.Errorf("failed to create embedded tfstate file: %s", err) 56 } 57 err = statefile.Write(stateFile, w) 58 if err != nil { 59 return fmt.Errorf("failed to write state snapshot: %s", err) 60 } 61 } 62 63 // tfstate-prev file 64 { 65 w, err := zw.CreateHeader(&zip.FileHeader{ 66 Name: tfstatePreviousFilename, 67 Method: zip.Deflate, 68 Modified: time.Now(), 69 }) 70 if err != nil { 71 return fmt.Errorf("failed to create embedded tfstate-prev file: %s", err) 72 } 73 err = statefile.Write(prevStateFile, w) 74 if err != nil { 75 return fmt.Errorf("failed to write previous state snapshot: %s", err) 76 } 77 } 78 79 // tfconfig directory 80 { 81 err := writeConfigSnapshot(configSnap, zw) 82 if err != nil { 83 return fmt.Errorf("failed to write config snapshot: %s", err) 84 } 85 } 86 87 return nil 88} 89