terraform: Validate called on provider

This commit is contained in:
Mitchell Hashimoto 2014-06-12 22:30:09 -07:00
parent 00a8c4f2ca
commit 8a2eb95a42
5 changed files with 76 additions and 1 deletions

View File

@ -1,9 +1,22 @@
package terraform
import (
"github.com/hashicorp/terraform/config"
)
// ResourceProvider is an interface that must be implemented by any
// resource provider: the thing that creates and manages the resources in
// a Terraform configuration.
type ResourceProvider interface {
// Validate is called once at the beginning with the raw configuration
// (no interpolation done) and can return a list of warnings and/or
// errors.
//
// This should not assume that any values of the configurations are valid.
// The primary use case of this call is to check that required keys are
// set.
Validate(*ResourceConfig) ([]string, []error)
// Configure configures the provider itself with the configuration
// given. This is useful for setting things like access keys.
//
@ -45,6 +58,14 @@ type ResourceType struct {
// of a resource provider.
type ResourceProviderFactory func() (ResourceProvider, error)
// NewResourceConfig creates a new ResourceConfig from a config.RawConfig.
func NewResourceConfig(c *config.RawConfig) *ResourceConfig {
return &ResourceConfig{
ComputedKeys: c.UnknownKeys(),
Raw: c.Raw,
}
}
func ProviderSatisfies(p ResourceProvider, n string) bool {
for _, rt := range p.Resources() {
if rt.Name == n {

View File

@ -17,6 +17,16 @@ type MockResourceProvider struct {
DiffReturnError error
ResourcesCalled bool
ResourcesReturn []ResourceType
ValidateCalled bool
ValidateConfig *ResourceConfig
ValidateReturnWarns []string
ValidateReturnErrors []error
}
func (p *MockResourceProvider) Validate(c *ResourceConfig) ([]string, []error) {
p.ValidateCalled = true
p.ValidateConfig = c
return p.ValidateReturnWarns, p.ValidateReturnErrors
}
func (p *MockResourceProvider) Configure(c *ResourceConfig) error {

View File

@ -60,6 +60,25 @@ func New(c *Config) (*Terraform, error) {
errs = append(errs, err...)
}
// Validate all the configurations, once.
tps := make(map[*terraformProvider]struct{})
for _, tp := range mapping {
if _, ok := tps[tp]; !ok {
tps[tp] = struct{}{}
}
}
for tp, _ := range tps {
var rc *ResourceConfig
if tp.Config != nil {
rc = NewResourceConfig(tp.Config.RawConfig)
}
_, tpErrs := tp.Provider.Validate(rc)
if len(tpErrs) > 0 {
errs = append(errs, tpErrs...)
}
}
// Build the resource graph
graph := c.Config.Graph()
if err := graph.Validate(); err != nil {
@ -190,7 +209,7 @@ func (t *terraformProvider) init(vars map[string]string) (err error) {
rc = &ResourceConfig{
ComputedKeys: t.Config.RawConfig.UnknownKeys(),
Raw: t.Config.RawConfig.Config(),
Raw: t.Config.RawConfig.Config(),
}
}

View File

@ -139,6 +139,26 @@ func TestNew_providerConfigCache(t *testing.T) {
}
}
func TestNew_providerValidate(t *testing.T) {
config := testConfig(t, "new-provider-validate")
tfConfig := &Config{
Config: config,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFunc("aws", []string{"aws_instance"}),
},
}
tf, err := New(tfConfig)
if err != nil {
t.Fatalf("err: %s", err)
}
p := testProviderMock(testProvider(tf, "aws_instance.foo"))
if !p.ValidateCalled {
t.Fatal("validate should be called")
}
}
func TestNew_variables(t *testing.T) {
config := testConfig(t, "new-variables")
tfConfig := &Config{

View File

@ -0,0 +1,5 @@
provider "aws" {
foo = "bar"
}
resource "aws_instance" "foo" {}