terraform: add some semantic check functions
This commit is contained in:
parent
d0577fda02
commit
c8c7d6baa3
|
@ -1,147 +1,24 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
/*
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
// smcUserVariables does all the semantic checks to verify that the
|
||||||
// smcProviders matches up the resources with a provider and initializes
|
// variables given satisfy the configuration itself.
|
||||||
// it. This does not call "Configure" on the ResourceProvider, since that
|
func smcUserVariables(c *config.Config, vs map[string]string) []error {
|
||||||
// might actually depend on upstream resources.
|
|
||||||
func smcProviders(
|
|
||||||
c *Config) (map[*config.Resource]*terraformProvider, []error) {
|
|
||||||
var errs []error
|
|
||||||
|
|
||||||
// Keep track of providers we know we couldn't instantiate so
|
|
||||||
// that we don't get a ton of errors about the same provider.
|
|
||||||
failures := make(map[string]struct{})
|
|
||||||
|
|
||||||
// Go through each resource and match it up to a provider
|
|
||||||
mapping := make(map[*config.Resource]*terraformProvider)
|
|
||||||
providers := make(map[string]ResourceProvider)
|
|
||||||
tpcache := make(map[string]*terraformProvider)
|
|
||||||
|
|
||||||
ResourceLoop:
|
|
||||||
for _, r := range c.Config.Resources {
|
|
||||||
// Find the prefixes that match this in the order of
|
|
||||||
// longest matching first (most specific)
|
|
||||||
prefixes := matchingPrefixes(r.Type, c.Providers)
|
|
||||||
if len(prefixes) > 0 {
|
|
||||||
if _, ok := failures[prefixes[0]]; ok {
|
|
||||||
// We already failed this provider, meaning this
|
|
||||||
// resource will never succeed, so just continue.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each prefix and instantiate if necessary, then
|
|
||||||
// verify if this provider is of use to us or not.
|
|
||||||
var providerName string
|
|
||||||
var provider ResourceProvider
|
|
||||||
for _, prefix := range prefixes {
|
|
||||||
// Initialize the provider
|
|
||||||
p, ok := providers[prefix]
|
|
||||||
if !ok {
|
|
||||||
var err error
|
|
||||||
p, err = c.Providers[prefix]()
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, fmt.Errorf(
|
|
||||||
"Error instantiating resource provider for "+
|
|
||||||
"prefix %s: %s", prefix, err))
|
|
||||||
|
|
||||||
// Record the error so that we don't check it again
|
|
||||||
failures[prefix] = struct{}{}
|
|
||||||
|
|
||||||
// Jump to the next resource
|
|
||||||
continue ResourceLoop
|
|
||||||
}
|
|
||||||
|
|
||||||
providers[prefix] = p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test if this provider matches what we need
|
|
||||||
if !ProviderSatisfies(p, r.Type) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
providerName = prefix
|
|
||||||
provider = p
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't find a valid provider, then error and continue
|
|
||||||
if providerName == "" {
|
|
||||||
errs = append(errs, fmt.Errorf(
|
|
||||||
"Provider for resource %s not found.",
|
|
||||||
r.Id()))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the matching provider configuration for this resource
|
|
||||||
var pc *config.ProviderConfig
|
|
||||||
pcName := config.ProviderConfigName(r.Type, c.Config.ProviderConfigs)
|
|
||||||
if pcName != "" {
|
|
||||||
pc = c.Config.ProviderConfigs[pcName]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up if we already have a provider for this pair of PC
|
|
||||||
// and provider name. If not, create it.
|
|
||||||
cacheKey := fmt.Sprintf("%s|%s", pcName, providerName)
|
|
||||||
tp, ok := tpcache[cacheKey]
|
|
||||||
if !ok {
|
|
||||||
renew := false
|
|
||||||
for _, tp := range tpcache {
|
|
||||||
if tp.Provider == provider {
|
|
||||||
renew = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if renew {
|
|
||||||
var err error
|
|
||||||
provider, err = c.Providers[providerName]()
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, fmt.Errorf(
|
|
||||||
"Error instantiating resource provider for "+
|
|
||||||
"prefix %s: %s", providerName, err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tp = &terraformProvider{
|
|
||||||
Provider: provider,
|
|
||||||
Config: pc,
|
|
||||||
}
|
|
||||||
tpcache[cacheKey] = tp
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping[r] = tp
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errs) > 0 {
|
|
||||||
return nil, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapping, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// smcVariables does all the semantic checks to verify that the
|
|
||||||
// variables given in the configuration to instantiate a Terraform
|
|
||||||
// struct are valid.
|
|
||||||
func smcVariables(c *Config) []error {
|
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
// Check that all required variables are present
|
// Check that all required variables are present
|
||||||
required := make(map[string]struct{})
|
required := make(map[string]struct{})
|
||||||
for k, v := range c.Config.Variables {
|
for k, v := range c.Variables {
|
||||||
if v.Required() {
|
if v.Required() {
|
||||||
required[k] = struct{}{}
|
required[k] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k, _ := range c.Variables {
|
for k, _ := range vs {
|
||||||
delete(required, k)
|
delete(required, k)
|
||||||
}
|
}
|
||||||
if len(required) > 0 {
|
if len(required) > 0 {
|
||||||
|
@ -155,4 +32,3 @@ func smcVariables(c *Config) []error {
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSMCUserVariables(t *testing.T) {
|
||||||
|
c := testConfig(t, "smc-uservars")
|
||||||
|
|
||||||
|
// Required variables not set
|
||||||
|
errs := smcUserVariables(c, nil)
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should have errors")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required variables set, optional variables unset
|
||||||
|
errs = smcUserVariables(c, map[string]string{"foo": "bar"})
|
||||||
|
if len(errs) != 0 {
|
||||||
|
t.Fatalf("err: %#v", errs)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Required
|
||||||
|
variable "foo" {
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
variable "bar" {
|
||||||
|
default = "baz"
|
||||||
|
}
|
Loading…
Reference in New Issue