github.com/cmalfait/terraform@v0.11.12-beta1/config/providers.go (about)

     1  package config
     2  
     3  import "github.com/blang/semver"
     4  
     5  // ProviderVersionConstraint presents a constraint for a particular
     6  // provider, identified by its full name.
     7  type ProviderVersionConstraint struct {
     8  	Constraint   string
     9  	ProviderType string
    10  }
    11  
    12  // ProviderVersionConstraints is a map from provider full name to its associated
    13  // ProviderVersionConstraint, as produced by Config.RequiredProviders.
    14  type ProviderVersionConstraints map[string]ProviderVersionConstraint
    15  
    16  // RequiredProviders returns the ProviderVersionConstraints for this
    17  // module.
    18  //
    19  // This includes both providers that are explicitly requested by provider
    20  // blocks and those that are used implicitly by instantiating one of their
    21  // resource types. In the latter case, the returned semver Range will
    22  // accept any version of the provider.
    23  func (c *Config) RequiredProviders() ProviderVersionConstraints {
    24  	ret := make(ProviderVersionConstraints, len(c.ProviderConfigs))
    25  
    26  	configs := c.ProviderConfigsByFullName()
    27  
    28  	// In order to find the *implied* dependencies (those without explicit
    29  	// "provider" blocks) we need to walk over all of the resources and
    30  	// cross-reference with the provider configs.
    31  	for _, rc := range c.Resources {
    32  		providerName := rc.ProviderFullName()
    33  		var providerType string
    34  
    35  		// Default to (effectively) no constraint whatsoever, but we might
    36  		// override if there's an explicit constraint in config.
    37  		constraint := ">=0.0.0"
    38  
    39  		config, ok := configs[providerName]
    40  		if ok {
    41  			if config.Version != "" {
    42  				constraint = config.Version
    43  			}
    44  			providerType = config.Name
    45  		} else {
    46  			providerType = providerName
    47  		}
    48  
    49  		ret[providerName] = ProviderVersionConstraint{
    50  			ProviderType: providerType,
    51  			Constraint:   constraint,
    52  		}
    53  	}
    54  
    55  	return ret
    56  }
    57  
    58  // RequiredRanges returns a semver.Range for each distinct provider type in
    59  // the constraint map. If the same provider type appears more than once
    60  // (e.g. because aliases are in use) then their respective constraints are
    61  // combined such that they must *all* apply.
    62  //
    63  // The result of this method can be passed to the
    64  // PluginMetaSet.ConstrainVersions method within the plugin/discovery
    65  // package in order to filter down the available plugins to those which
    66  // satisfy the given constraints.
    67  //
    68  // This function will panic if any of the constraints within cannot be
    69  // parsed as semver ranges. This is guaranteed to never happen for a
    70  // constraint set that was built from a configuration that passed validation.
    71  func (cons ProviderVersionConstraints) RequiredRanges() map[string]semver.Range {
    72  	ret := make(map[string]semver.Range, len(cons))
    73  
    74  	for _, con := range cons {
    75  		spec := semver.MustParseRange(con.Constraint)
    76  		if existing, exists := ret[con.ProviderType]; exists {
    77  			ret[con.ProviderType] = existing.AND(spec)
    78  		} else {
    79  			ret[con.ProviderType] = spec
    80  		}
    81  	}
    82  
    83  	return ret
    84  }
    85  
    86  // ProviderConfigsByFullName returns a map from provider full names (as
    87  // returned by ProviderConfig.FullName()) to the corresponding provider
    88  // configs.
    89  //
    90  // This function returns no new information than what's already in
    91  // c.ProviderConfigs, but returns it in a more convenient shape. If there
    92  // is more than one provider config with the same full name then the result
    93  // is undefined, but that is guaranteed not to happen for any config that
    94  // has passed validation.
    95  func (c *Config) ProviderConfigsByFullName() map[string]*ProviderConfig {
    96  	ret := make(map[string]*ProviderConfig, len(c.ProviderConfigs))
    97  
    98  	for _, pc := range c.ProviderConfigs {
    99  		ret[pc.FullName()] = pc
   100  	}
   101  
   102  	return ret
   103  }