github.com/mingfang/terraform@v0.11.12-beta1/terraform/eval_provider.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/config" 7 ) 8 9 // EvalBuildProviderConfig outputs a *ResourceConfig that is properly 10 // merged with parents and inputs on top of what is configured in the file. 11 type EvalBuildProviderConfig struct { 12 Provider string 13 Config **ResourceConfig 14 Output **ResourceConfig 15 } 16 17 func (n *EvalBuildProviderConfig) Eval(ctx EvalContext) (interface{}, error) { 18 cfg := *n.Config 19 20 // If we have an Input configuration set, then merge that in 21 if input := ctx.ProviderInput(n.Provider); input != nil { 22 // "input" is a map of the subset of config values that were known 23 // during the input walk, set by EvalInputProvider. Note that 24 // in particular it does *not* include attributes that had 25 // computed values at input time; those appear *only* in 26 // "cfg" here. 27 rc, err := config.NewRawConfig(input) 28 if err != nil { 29 return nil, err 30 } 31 32 merged := rc.Merge(cfg.raw) 33 cfg = NewResourceConfig(merged) 34 } 35 36 *n.Output = cfg 37 return nil, nil 38 } 39 40 // EvalConfigProvider is an EvalNode implementation that configures 41 // a provider that is already initialized and retrieved. 42 type EvalConfigProvider struct { 43 Provider string 44 Config **ResourceConfig 45 } 46 47 func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { 48 return nil, ctx.ConfigureProvider(n.Provider, *n.Config) 49 } 50 51 // EvalInitProvider is an EvalNode implementation that initializes a provider 52 // and returns nothing. The provider can be retrieved again with the 53 // EvalGetProvider node. 54 type EvalInitProvider struct { 55 TypeName string 56 Name string 57 } 58 59 func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) { 60 return ctx.InitProvider(n.TypeName, n.Name) 61 } 62 63 // EvalCloseProvider is an EvalNode implementation that closes provider 64 // connections that aren't needed anymore. 65 type EvalCloseProvider struct { 66 Name string 67 } 68 69 func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) { 70 ctx.CloseProvider(n.Name) 71 return nil, nil 72 } 73 74 // EvalGetProvider is an EvalNode implementation that retrieves an already 75 // initialized provider instance for the given name. 76 type EvalGetProvider struct { 77 Name string 78 Output *ResourceProvider 79 } 80 81 func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { 82 result := ctx.Provider(n.Name) 83 if result == nil { 84 return nil, fmt.Errorf("provider %s not initialized", n.Name) 85 } 86 87 if n.Output != nil { 88 *n.Output = result 89 } 90 91 return nil, nil 92 } 93 94 // EvalInputProvider is an EvalNode implementation that asks for input 95 // for the given provider configurations. 96 type EvalInputProvider struct { 97 Name string 98 Provider *ResourceProvider 99 Config **ResourceConfig 100 } 101 102 func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) { 103 rc := *n.Config 104 orig := rc.DeepCopy() 105 106 // Wrap the input into a namespace 107 input := &PrefixUIInput{ 108 IdPrefix: fmt.Sprintf("provider.%s", n.Name), 109 QueryPrefix: fmt.Sprintf("provider.%s.", n.Name), 110 UIInput: ctx.Input(), 111 } 112 113 // Go through each provider and capture the input necessary 114 // to satisfy it. 115 config, err := (*n.Provider).Input(input, rc) 116 if err != nil { 117 return nil, fmt.Errorf( 118 "Error configuring %s: %s", n.Name, err) 119 } 120 121 // We only store values that have changed through Input. 122 // The goal is to cache cache input responses, not to provide a complete 123 // config for other providers. 124 confMap := make(map[string]interface{}) 125 if config != nil && len(config.Config) > 0 { 126 // any values that weren't in the original ResourcConfig will be cached 127 for k, v := range config.Config { 128 if _, ok := orig.Config[k]; !ok { 129 confMap[k] = v 130 } 131 } 132 } 133 134 ctx.SetProviderInput(n.Name, confMap) 135 136 return nil, nil 137 }