github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/plans/plan.go (about) 1 package plans 2 3 import ( 4 "sort" 5 6 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 7 "github.com/hashicorp/terraform-plugin-sdk/internal/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. 22 type 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. 32 type 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 49 func 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. 66 func (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 }