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  }