1package plans 2 3import ( 4 "sort" 5 6 "github.com/hashicorp/terraform/addrs" 7 "github.com/hashicorp/terraform/configs/configschema" 8 "github.com/zclconf/go-cty/cty" 9) 10 11// Plan is the top-level type representing a planned set of changes. 12// 13// A plan is a summary of the set of changes required to move from a current 14// state to a goal state derived from configuration. The described changes 15// are not applied directly, but contain an approximation of the final 16// result that will be completed during apply by resolving any values that 17// cannot be predicted. 18// 19// A plan must always be accompanied by the state and configuration it was 20// built from, since the plan does not itself include all of the information 21// required to make the changes indicated. 22type Plan struct { 23 VariableValues map[string]DynamicValue 24 Changes *Changes 25 TargetAddrs []addrs.Targetable 26 ProviderSHA256s map[string][]byte 27 Backend Backend 28} 29 30// Backend represents the backend-related configuration and other data as it 31// existed when a plan was created. 32type Backend struct { 33 // Type is the type of backend that the plan will apply against. 34 Type string 35 36 // Config is the configuration of the backend, whose schema is decided by 37 // the backend Type. 38 Config DynamicValue 39 40 // Workspace is the name of the workspace that was active when the plan 41 // was created. It is illegal to apply a plan created for one workspace 42 // to the state of another workspace. 43 // (This constraint is already enforced by the statefile lineage mechanism, 44 // but storing this explicitly allows us to return a better error message 45 // in the situation where the user has the wrong workspace selected.) 46 Workspace string 47} 48 49func NewBackend(typeName string, config cty.Value, configSchema *configschema.Block, workspaceName string) (*Backend, error) { 50 dv, err := NewDynamicValue(config, configSchema.ImpliedType()) 51 if err != nil { 52 return nil, err 53 } 54 55 return &Backend{ 56 Type: typeName, 57 Config: dv, 58 Workspace: workspaceName, 59 }, nil 60} 61 62// ProviderAddrs returns a list of all of the provider configuration addresses 63// referenced throughout the receiving plan. 64// 65// The result is de-duplicated so that each distinct address appears only once. 66func (p *Plan) ProviderAddrs() []addrs.AbsProviderConfig { 67 if p == nil || p.Changes == nil { 68 return nil 69 } 70 71 m := map[string]addrs.AbsProviderConfig{} 72 for _, rc := range p.Changes.Resources { 73 m[rc.ProviderAddr.String()] = rc.ProviderAddr 74 } 75 if len(m) == 0 { 76 return nil 77 } 78 79 // This is mainly just so we'll get stable results for testing purposes. 80 keys := make([]string, 0, len(m)) 81 for k := range m { 82 keys = append(keys, k) 83 } 84 sort.Strings(keys) 85 86 ret := make([]addrs.AbsProviderConfig, len(keys)) 87 for i, key := range keys { 88 ret[i] = m[key] 89 } 90 91 return ret 92} 93