github.com/sylr/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 }