1package terraform 2 3import ( 4 "bytes" 5 "encoding/gob" 6 "fmt" 7 "io" 8 "sync" 9 10 "github.com/zclconf/go-cty/cty" 11 12 "github.com/hashicorp/terraform/configs" 13) 14 15func init() { 16 gob.Register(make([]interface{}, 0)) 17 gob.Register(make([]map[string]interface{}, 0)) 18 gob.Register(make(map[string]interface{})) 19 gob.Register(make(map[string]string)) 20} 21 22// Plan represents a single Terraform execution plan, which contains 23// all the information necessary to make an infrastructure change. 24// 25// A plan has to contain basically the entire state of the world 26// necessary to make a change: the state, diff, config, backend config, etc. 27// This is so that it can run alone without any other data. 28type Plan struct { 29 // Diff describes the resource actions that must be taken when this 30 // plan is applied. 31 Diff *Diff 32 33 // Config represents the entire configuration that was present when this 34 // plan was created. 35 Config *configs.Config 36 37 // State is the Terraform state that was current when this plan was 38 // created. 39 // 40 // It is not allowed to apply a plan that has a stale state, since its 41 // diff could be outdated. 42 State *State 43 44 // Vars retains the variables that were set when creating the plan, so 45 // that the same variables can be applied during apply. 46 Vars map[string]cty.Value 47 48 // Targets, if non-empty, contains a set of resource address strings that 49 // identify graph nodes that were selected as targets for plan. 50 // 51 // When targets are set, any graph node that is not directly targeted or 52 // indirectly targeted via dependencies is excluded from the graph. 53 Targets []string 54 55 // TerraformVersion is the version of Terraform that was used to create 56 // this plan. 57 // 58 // It is not allowed to apply a plan created with a different version of 59 // Terraform, since the other fields of this structure may be interpreted 60 // in different ways between versions. 61 TerraformVersion string 62 63 // ProviderSHA256s is a map giving the SHA256 hashes of the exact binaries 64 // used as plugins for each provider during plan. 65 // 66 // These must match between plan and apply to ensure that the diff is 67 // correctly interpreted, since different provider versions may have 68 // different attributes or attribute value constraints. 69 ProviderSHA256s map[string][]byte 70 71 // Backend is the backend that this plan should use and store data with. 72 Backend *BackendState 73 74 // Destroy indicates that this plan was created for a full destroy operation 75 Destroy bool 76 77 once sync.Once 78} 79 80func (p *Plan) String() string { 81 buf := new(bytes.Buffer) 82 buf.WriteString("DIFF:\n\n") 83 buf.WriteString(p.Diff.String()) 84 buf.WriteString("\n\nSTATE:\n\n") 85 buf.WriteString(p.State.String()) 86 return buf.String() 87} 88 89func (p *Plan) init() { 90 p.once.Do(func() { 91 if p.Diff == nil { 92 p.Diff = new(Diff) 93 p.Diff.init() 94 } 95 96 if p.State == nil { 97 p.State = new(State) 98 p.State.init() 99 } 100 101 if p.Vars == nil { 102 p.Vars = make(map[string]cty.Value) 103 } 104 }) 105} 106 107// The format byte is prefixed into the plan file format so that we have 108// the ability in the future to change the file format if we want for any 109// reason. 110const planFormatMagic = "tfplan" 111const planFormatVersion byte = 2 112 113// ReadPlan reads a plan structure out of a reader in the format that 114// was written by WritePlan. 115func ReadPlan(src io.Reader) (*Plan, error) { 116 return nil, fmt.Errorf("terraform.ReadPlan is no longer in use; use planfile.Open instead") 117} 118 119// WritePlan writes a plan somewhere in a binary format. 120func WritePlan(d *Plan, dst io.Writer) error { 121 return fmt.Errorf("terraform.WritePlan is no longer in use; use planfile.Create instead") 122} 123