github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/terraform/eval_provider.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/config" 7 ) 8 9 // EvalSetProviderConfig sets the parent configuration for a provider 10 // without configuring that provider, validating it, etc. 11 type EvalSetProviderConfig struct { 12 Provider string 13 Config **ResourceConfig 14 } 15 16 func (n *EvalSetProviderConfig) Eval(ctx EvalContext) (interface{}, error) { 17 return nil, ctx.SetProviderConfig(n.Provider, *n.Config) 18 } 19 20 // EvalBuildProviderConfig outputs a *ResourceConfig that is properly 21 // merged with parents and inputs on top of what is configured in the file. 22 type EvalBuildProviderConfig struct { 23 Provider string 24 Config **ResourceConfig 25 Output **ResourceConfig 26 } 27 28 func (n *EvalBuildProviderConfig) Eval(ctx EvalContext) (interface{}, error) { 29 cfg := *n.Config 30 31 // If we have a configuration set, then merge that in 32 if input := ctx.ProviderInput(n.Provider); input != nil { 33 // "input" is a map of the subset of config values that were known 34 // during the input walk, set by EvalInputProvider. Note that 35 // in particular it does *not* include attributes that had 36 // computed values at input time; those appear *only* in 37 // "cfg" here. 38 rc, err := config.NewRawConfig(input) 39 if err != nil { 40 return nil, err 41 } 42 43 merged := cfg.raw.Merge(rc) 44 cfg = NewResourceConfig(merged) 45 } 46 47 // Get the parent configuration if there is one 48 if parent := ctx.ParentProviderConfig(n.Provider); parent != nil { 49 merged := cfg.raw.Merge(parent.raw) 50 cfg = NewResourceConfig(merged) 51 } 52 53 *n.Output = cfg 54 return nil, nil 55 } 56 57 // EvalConfigProvider is an EvalNode implementation that configures 58 // a provider that is already initialized and retrieved. 59 type EvalConfigProvider struct { 60 Provider string 61 Config **ResourceConfig 62 } 63 64 func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { 65 return nil, ctx.ConfigureProvider(n.Provider, *n.Config) 66 } 67 68 // EvalInitProvider is an EvalNode implementation that initializes a provider 69 // and returns nothing. The provider can be retrieved again with the 70 // EvalGetProvider node. 71 type EvalInitProvider struct { 72 Name string 73 } 74 75 func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) { 76 return ctx.InitProvider(n.Name) 77 } 78 79 // EvalCloseProvider is an EvalNode implementation that closes provider 80 // connections that aren't needed anymore. 81 type EvalCloseProvider struct { 82 Name string 83 } 84 85 func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) { 86 ctx.CloseProvider(n.Name) 87 return nil, nil 88 } 89 90 // EvalGetProvider is an EvalNode implementation that retrieves an already 91 // initialized provider instance for the given name. 92 type EvalGetProvider struct { 93 Name string 94 Output *ResourceProvider 95 } 96 97 func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { 98 result := ctx.Provider(n.Name) 99 if result == nil { 100 return nil, fmt.Errorf("provider %s not initialized", n.Name) 101 } 102 103 if n.Output != nil { 104 *n.Output = result 105 } 106 107 return nil, nil 108 } 109 110 // EvalInputProvider is an EvalNode implementation that asks for input 111 // for the given provider configurations. 112 type EvalInputProvider struct { 113 Name string 114 Provider *ResourceProvider 115 Config **ResourceConfig 116 } 117 118 func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) { 119 // If we already configured this provider, then don't do this again 120 if v := ctx.ProviderInput(n.Name); v != nil { 121 return nil, nil 122 } 123 124 rc := *n.Config 125 126 // Wrap the input into a namespace 127 input := &PrefixUIInput{ 128 IdPrefix: fmt.Sprintf("provider.%s", n.Name), 129 QueryPrefix: fmt.Sprintf("provider.%s.", n.Name), 130 UIInput: ctx.Input(), 131 } 132 133 // Go through each provider and capture the input necessary 134 // to satisfy it. 135 config, err := (*n.Provider).Input(input, rc) 136 if err != nil { 137 return nil, fmt.Errorf( 138 "Error configuring %s: %s", n.Name, err) 139 } 140 141 // Set the input that we received so that child modules don't attempt 142 // to ask for input again. 143 if config != nil && len(config.Config) > 0 { 144 // This repository of provider input results on the context doesn't 145 // retain config.ComputedKeys, so we need to filter those out here 146 // in order that later users of this data won't try to use the unknown 147 // value placeholder as if it were a literal value. This map is just 148 // of known values we've been able to complete so far; dynamic stuff 149 // will be merged in by EvalBuildProviderConfig on subsequent 150 // (post-input) walks. 151 confMap := config.Config 152 if config.ComputedKeys != nil { 153 for _, key := range config.ComputedKeys { 154 delete(confMap, key) 155 } 156 } 157 158 ctx.SetProviderInput(n.Name, confMap) 159 } else { 160 ctx.SetProviderInput(n.Name, map[string]interface{}{}) 161 } 162 163 return nil, nil 164 }