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  }