github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/plans/planfile/writer.go (about)

     1  package planfile
     2  
     3  import (
     4  	"archive/zip"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/internal/configs/configload"
    10  	"github.com/hashicorp/terraform/internal/depsfile"
    11  	"github.com/hashicorp/terraform/internal/plans"
    12  	"github.com/hashicorp/terraform/internal/states/statefile"
    13  )
    14  
    15  type CreateArgs struct {
    16  	// ConfigSnapshot is a snapshot of the configuration that the plan
    17  	// was created from.
    18  	ConfigSnapshot *configload.Snapshot
    19  
    20  	// PreviousRunStateFile is a representation of the state snapshot we used
    21  	// as the original input when creating this plan, containing the same
    22  	// information as recorded at the end of the previous apply except for
    23  	// upgrading managed resource instance data to the provider's latest
    24  	// schema versions.
    25  	PreviousRunStateFile *statefile.File
    26  
    27  	// BaseStateFile is a representation of the state snapshot we used to
    28  	// create the plan, which is the result of asking the providers to refresh
    29  	// all previously-stored objects to match the current situation in the
    30  	// remote system. (If this plan was created with refreshing disabled,
    31  	// this should be the same as PreviousRunStateFile.)
    32  	StateFile *statefile.File
    33  
    34  	// Plan records the plan itself, which is the main artifact inside a
    35  	// saved plan file.
    36  	Plan *plans.Plan
    37  
    38  	// DependencyLocks records the dependency lock information that we
    39  	// checked prior to creating the plan, so we can make sure that all of the
    40  	// same dependencies are still available when applying the plan.
    41  	DependencyLocks *depsfile.Locks
    42  }
    43  
    44  // Create creates a new plan file with the given filename, overwriting any
    45  // file that might already exist there.
    46  //
    47  // A plan file contains both a snapshot of the configuration and of the latest
    48  // state file in addition to the plan itself, so that Terraform can detect
    49  // if the world has changed since the plan was created and thus refuse to
    50  // apply it.
    51  func Create(filename string, args CreateArgs) error {
    52  	f, err := os.Create(filename)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	defer f.Close()
    57  
    58  	zw := zip.NewWriter(f)
    59  	defer zw.Close()
    60  
    61  	// tfplan file
    62  	{
    63  		w, err := zw.CreateHeader(&zip.FileHeader{
    64  			Name:     tfplanFilename,
    65  			Method:   zip.Deflate,
    66  			Modified: time.Now(),
    67  		})
    68  		if err != nil {
    69  			return fmt.Errorf("failed to create tfplan file: %s", err)
    70  		}
    71  		err = writeTfplan(args.Plan, w)
    72  		if err != nil {
    73  			return fmt.Errorf("failed to write plan: %s", err)
    74  		}
    75  	}
    76  
    77  	// tfstate file
    78  	{
    79  		w, err := zw.CreateHeader(&zip.FileHeader{
    80  			Name:     tfstateFilename,
    81  			Method:   zip.Deflate,
    82  			Modified: time.Now(),
    83  		})
    84  		if err != nil {
    85  			return fmt.Errorf("failed to create embedded tfstate file: %s", err)
    86  		}
    87  		err = statefile.Write(args.StateFile, w)
    88  		if err != nil {
    89  			return fmt.Errorf("failed to write state snapshot: %s", err)
    90  		}
    91  	}
    92  
    93  	// tfstate-prev file
    94  	{
    95  		w, err := zw.CreateHeader(&zip.FileHeader{
    96  			Name:     tfstatePreviousFilename,
    97  			Method:   zip.Deflate,
    98  			Modified: time.Now(),
    99  		})
   100  		if err != nil {
   101  			return fmt.Errorf("failed to create embedded tfstate-prev file: %s", err)
   102  		}
   103  		err = statefile.Write(args.PreviousRunStateFile, w)
   104  		if err != nil {
   105  			return fmt.Errorf("failed to write previous state snapshot: %s", err)
   106  		}
   107  	}
   108  
   109  	// tfconfig directory
   110  	{
   111  		err := writeConfigSnapshot(args.ConfigSnapshot, zw)
   112  		if err != nil {
   113  			return fmt.Errorf("failed to write config snapshot: %s", err)
   114  		}
   115  	}
   116  
   117  	// .terraform.lock.hcl file, containing dependency lock information
   118  	if args.DependencyLocks != nil { // (this was a later addition, so not all callers set it, but main callers should)
   119  		src, diags := depsfile.SaveLocksToBytes(args.DependencyLocks)
   120  		if diags.HasErrors() {
   121  			return fmt.Errorf("failed to write embedded dependency lock file: %s", diags.Err().Error())
   122  		}
   123  
   124  		w, err := zw.CreateHeader(&zip.FileHeader{
   125  			Name:     dependencyLocksFilename,
   126  			Method:   zip.Deflate,
   127  			Modified: time.Now(),
   128  		})
   129  		if err != nil {
   130  			return fmt.Errorf("failed to create embedded dependency lock file: %s", err)
   131  		}
   132  		_, err = w.Write(src)
   133  		if err != nil {
   134  			return fmt.Errorf("failed to write embedded dependency lock file: %s", err)
   135  		}
   136  	}
   137  
   138  	return nil
   139  }