terraform/helper/schema/provider.go

189 lines
5.2 KiB
Go
Raw Normal View History

2014-08-17 23:45:43 +02:00
package schema
import (
"errors"
2014-08-17 23:45:43 +02:00
"fmt"
2014-08-18 04:32:11 +02:00
"sort"
2014-08-17 23:45:43 +02:00
"github.com/hashicorp/terraform/terraform"
)
2014-08-27 06:52:09 +02:00
// Provider represents a resource provider in Terraform, and properly
2014-08-17 23:45:43 +02:00
// implements all of the ResourceProvider API.
//
2014-08-27 06:52:09 +02:00
// By defining a schema for the configuration of the provider, the
// map of supporting resources, and a configuration function, the schema
// framework takes over and handles all the provider operations for you.
//
// After defining the provider structure, it is unlikely that you'll require any
// of the methods on Provider itself.
2014-08-17 23:45:43 +02:00
type Provider struct {
2014-08-27 06:52:09 +02:00
// Schema is the schema for the configuration of this provider. If this
// provider has no configuration, this can be omitted.
//
// The keys of this map are the configuration keys, and the value is
// the schema describing the value of the configuration.
2014-08-18 00:07:01 +02:00
Schema map[string]*Schema
2014-08-27 06:52:09 +02:00
// ResourcesMap is the list of available resources that this provider
// can manage, along with their Resource structure defining their
// own schemas and CRUD operations.
//
// Provider automatically handles routing operations such as Apply,
// Diff, etc. to the proper resource.
2014-08-18 00:07:01 +02:00
ResourcesMap map[string]*Resource
2014-08-17 23:45:43 +02:00
2014-08-27 06:52:09 +02:00
// ConfigureFunc is a function for configuring the provider. If the
// provider doesn't need to be configured, this can be omitted.
//
// See the ConfigureFunc documentation for more information.
ConfigureFunc ConfigureFunc
2014-08-18 04:45:26 +02:00
meta interface{}
2014-08-17 23:45:43 +02:00
}
// ConfigureFunc is the function used to configure a Provider.
2014-08-18 04:45:26 +02:00
//
// The interface{} value returned by this function is stored and passed into
2014-08-27 06:52:09 +02:00
// the subsequent resources as the meta parameter. This return value is
// usually used to pass along a configured API client, a configuration
// structure, etc.
2014-08-18 04:45:26 +02:00
type ConfigureFunc func(*ResourceData) (interface{}, error)
2014-08-17 23:45:43 +02:00
// InternalValidate should be called to validate the structure
// of the provider.
//
// This should be called in a unit test for any provider to verify
// before release that a provider is properly configured for use with
// this library.
func (p *Provider) InternalValidate() error {
if p == nil {
return errors.New("provider is nil")
}
if err := schemaMap(p.Schema).InternalValidate(); err != nil {
return err
}
for k, r := range p.ResourcesMap {
if err := r.InternalValidate(); err != nil {
return fmt.Errorf("%s: %s", k, err)
}
}
return nil
}
// Meta returns the metadata associated with this provider that was
// returned by the Configure call. It will be nil until Configure is called.
func (p *Provider) Meta() interface{} {
return p.meta
}
// SetMeta can be used to forcefully set the Meta object of the provider.
// Note that if Configure is called the return value will override anything
// set here.
func (p *Provider) SetMeta(v interface{}) {
p.meta = v
}
2014-08-27 06:52:09 +02:00
// Validate implementation of terraform.ResourceProvider interface.
2014-08-17 23:45:43 +02:00
func (p *Provider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
return schemaMap(p.Schema).Validate(c)
}
2014-08-27 06:52:09 +02:00
// ValidateResource implementation of terraform.ResourceProvider interface.
2014-08-17 23:45:43 +02:00
func (p *Provider) ValidateResource(
t string, c *terraform.ResourceConfig) ([]string, []error) {
2014-08-18 00:07:01 +02:00
r, ok := p.ResourcesMap[t]
2014-08-17 23:45:43 +02:00
if !ok {
return nil, []error{fmt.Errorf(
"Provider doesn't support resource: %s", t)}
}
return r.Validate(c)
}
// Configure implementation of terraform.ResourceProvider interface.
func (p *Provider) Configure(c *terraform.ResourceConfig) error {
// No configuration
if p.ConfigureFunc == nil {
return nil
}
sm := schemaMap(p.Schema)
// Get a ResourceData for this configuration. To do this, we actually
// generate an intermediary "diff" although that is never exposed.
diff, err := sm.Diff(nil, c)
if err != nil {
return err
}
data, err := sm.Data(nil, diff)
if err != nil {
return err
}
2014-08-18 04:45:26 +02:00
meta, err := p.ConfigureFunc(data)
if err != nil {
return err
}
p.meta = meta
return nil
}
2014-08-18 00:07:01 +02:00
// Apply implementation of terraform.ResourceProvider interface.
func (p *Provider) Apply(
s *terraform.ResourceState,
d *terraform.ResourceDiff) (*terraform.ResourceState, error) {
r, ok := p.ResourcesMap[s.Type]
if !ok {
return nil, fmt.Errorf("unknown resource type: %s", s.Type)
}
return r.Apply(s, d, p.meta)
}
// Diff implementation of terraform.ResourceProvider interface.
func (p *Provider) Diff(
s *terraform.ResourceState,
c *terraform.ResourceConfig) (*terraform.ResourceDiff, error) {
r, ok := p.ResourcesMap[s.Type]
if !ok {
return nil, fmt.Errorf("unknown resource type: %s", s.Type)
}
return r.Diff(s, c)
}
// Refresh implementation of terraform.ResourceProvider interface.
func (p *Provider) Refresh(
s *terraform.ResourceState) (*terraform.ResourceState, error) {
r, ok := p.ResourcesMap[s.Type]
if !ok {
return nil, fmt.Errorf("unknown resource type: %s", s.Type)
}
return r.Refresh(s, p.meta)
}
2014-08-18 00:07:01 +02:00
// Resources implementation of terraform.ResourceProvider interface.
func (p *Provider) Resources() []terraform.ResourceType {
2014-08-18 04:32:11 +02:00
keys := make([]string, 0, len(p.ResourcesMap))
2014-08-18 00:07:01 +02:00
for k, _ := range p.ResourcesMap {
2014-08-18 04:32:11 +02:00
keys = append(keys, k)
}
sort.Strings(keys)
result := make([]terraform.ResourceType, 0, len(keys))
for _, k := range keys {
2014-08-18 00:07:01 +02:00
result = append(result, terraform.ResourceType{
Name: k,
})
}
return result
}