helper/schema: documentation

This commit is contained in:
Mitchell Hashimoto 2014-08-26 21:52:09 -07:00
parent fb9810ca5c
commit 0c9b65f3f4
4 changed files with 133 additions and 35 deletions

View File

@ -8,15 +8,35 @@ import (
"github.com/hashicorp/terraform/terraform"
)
// Provider represents a Resource provider in Terraform, and properly
// Provider represents a resource provider in Terraform, and properly
// implements all of the ResourceProvider API.
//
// This is a friendlier API than the core Terraform ResourceProvider API,
// and is recommended to be used over that.
// 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.
type Provider struct {
// 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.
Schema map[string]*Schema
// 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.
ResourcesMap map[string]*Resource
// 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
meta interface{}
@ -25,7 +45,9 @@ type Provider struct {
// ConfigureFunc is the function used to configure a Provider.
//
// The interface{} value returned by this function is stored and passed into
// the subsequent resources as the meta parameter.
// the subsequent resources as the meta parameter. This return value is
// usually used to pass along a configured API client, a configuration
// structure, etc.
type ConfigureFunc func(*ResourceData) (interface{}, error)
// InternalValidate should be called to validate the structure
@ -65,13 +87,12 @@ func (p *Provider) SetMeta(v interface{}) {
p.meta = v
}
// Validate validates the provider configuration against the schema.
// Validate implementation of terraform.ResourceProvider interface.
func (p *Provider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
return schemaMap(p.Schema).Validate(c)
}
// ValidateResource validates the resource configuration against the
// proper schema.
// ValidateResource implementation of terraform.ResourceProvider interface.
func (p *Provider) ValidateResource(
t string, c *terraform.ResourceConfig) ([]string, []error) {
r, ok := p.ResourcesMap[t]

View File

@ -7,31 +7,58 @@ import (
"github.com/hashicorp/terraform/terraform"
)
// The functions below are the CRUD function types for a Resource.
//
// The second parameter is the meta value sent to the resource when
// different operations are called.
type CreateFunc func(*ResourceData, interface{}) error
type ReadFunc func(*ResourceData, interface{}) error
type UpdateFunc func(*ResourceData, interface{}) error
type DeleteFunc func(*ResourceData, interface{}) error
// Resource represents a thing in Terraform that has a set of configurable
// attributes and generally also has a lifecycle (create, read, update,
// delete).
// attributes and a lifecycle (create, read, update, delete).
//
// The Resource schema is an abstraction that allows provider writers to
// worry only about CRUD operations while off-loading validation, diff
// generation, etc. to this higher level library.
type Resource struct {
// Schema is the schema for the configuration of this resource.
//
// The keys of this map are the configuration keys, and the values
// describe the schema of the configuration value.
//
// The schema is used to represent both configurable data as well
// as data that might be computed in the process of creating this
// resource.
Schema map[string]*Schema
// The functions below are the CRUD operations for this resource.
//
// The only optional operation is Update. If Update is not implemented,
// then updates will not be supported for this resource.
//
// The ResourceData parameter in the functions below are used to
// query configuration and changes for the resource as well as to set
// the ID, computed data, etc.
//
// The interface{} parameter is the result of the ConfigureFunc in
// the provider for this resource. If the provider does not define
// a ConfigureFunc, this will be nil. This parameter should be used
// to store API clients, configuration structures, etc.
//
// If any errors occur during each of the operation, an error should be
// returned. If a resource was partially updated, be careful to enable
// partial state mode for ResourceData and use it accordingly.
Create CreateFunc
Read ReadFunc
Update UpdateFunc
Delete DeleteFunc
}
// See Resource documentation.
type CreateFunc func(*ResourceData, interface{}) error
// See Resource documentation.
type ReadFunc func(*ResourceData, interface{}) error
// See Resource documentation.
type UpdateFunc func(*ResourceData, interface{}) error
// See Resource documentation.
type DeleteFunc func(*ResourceData, interface{}) error
// Apply creates, updates, and/or deletes a resource.
func (r *Resource) Apply(
s *terraform.ResourceState,
@ -121,6 +148,10 @@ func (r *Resource) Refresh(
// This should be called in a unit test for any resource to verify
// before release that a resource is properly configured for use with
// this library.
//
// Provider.InternalValidate() will automatically call this for all of
// the resources it manages, so you don't need to call this manually if it
// is part of a Provider.
func (r *Resource) InternalValidate() error {
if r == nil {
return errors.New("resource is nil")

View File

@ -11,6 +11,30 @@ import (
"github.com/mitchellh/mapstructure"
)
// ResourceData is used to query and set the attributes of a resource.
//
// ResourceData is the primary argument received for CRUD operations on
// a resource as well as configuration of a provider. It is a powerful
// structure that can be used to not only query data, but check for changes,
// define partial state updates, etc.
//
// The most relevant methods to take a look at are Get, Set, and Partial.
type ResourceData struct {
// Settable (internally)
schema map[string]*Schema
config *terraform.ResourceConfig
state *terraform.ResourceState
diff *terraform.ResourceDiff
diffing bool
// Don't set
setMap map[string]string
newState *terraform.ResourceState
partial bool
partialMap map[string]struct{}
once sync.Once
}
// getSource represents the level we want to get for a value (internally).
// Any source less than or equal to the level will be loaded (whichever
// has a value first).
@ -34,21 +58,6 @@ type getResult struct {
var getResultEmpty getResult
// ResourceData is used to query and set the attributes of a resource.
type ResourceData struct {
schema map[string]*Schema
config *terraform.ResourceConfig
state *terraform.ResourceState
diff *terraform.ResourceDiff
diffing bool
setMap map[string]string
newState *terraform.ResourceState
partial bool
partialMap map[string]struct{}
once sync.Once
}
// Get returns the data for the given key, or nil if the key doesn't exist
// in the schema.
//
@ -56,7 +65,8 @@ type ResourceData struct {
// then the default value for that type will be returned. For strings, this is
// "", for numbers it is 0, etc.
//
// If you also want to test if something is set at all, use GetOk.
// If you want to test if something is set at all in the configuration,
// use GetOk.
func (d *ResourceData) Get(key string) interface{} {
v, _ := d.GetOk(key)
return v
@ -64,7 +74,10 @@ func (d *ResourceData) Get(key string) interface{} {
// GetChange returns the old and new value for a given key.
//
// If there is no change, then old and new will simply be the same.
// HasChange should be used to check if a change exists. It is possible
// that both the old and new value are the same if the old value was not
// set and the new value is. This is common, for example, for boolean
// fields which have a zero value of false.
func (d *ResourceData) GetChange(key string) (interface{}, interface{}) {
o, n := d.getChange(key, getSourceConfig, getSourceDiff)
return o.Value, n.Value
@ -73,6 +86,9 @@ func (d *ResourceData) GetChange(key string) (interface{}, interface{}) {
// GetOk returns the data for the given key and whether or not the key
// existed or not in the configuration. The second boolean result will also
// be false if a key is given that isn't in the schema at all.
//
// The first result will not necessarilly be nil if the value doesn't exist.
// The second result should be checked to determine this information.
func (d *ResourceData) GetOk(key string) (interface{}, bool) {
r := d.getRaw(key, getSourceSet)
return r.Value, r.Exists
@ -98,6 +114,9 @@ func (d *ResourceData) HasChange(key string) bool {
// When partial state mode is enabled, then only key prefixes specified
// by SetPartial will be in the final state. This allows providers to return
// partial states for partially applied resources (when errors occur).
//
// When partial state mode is toggled, the map of enabled partial states
// (by SetPartial) is reset.
func (d *ResourceData) Partial(on bool) {
d.partial = on
if on {

View File

@ -1,3 +1,14 @@
// schema is a high-level framework for easily writing new providers
// for Terraform. Usage of schema is recommended over attempting to write
// to the low-level plugin interfaces manually.
//
// schema breaks down provider creation into simple CRUD operations for
// resources. The logic of diffing, destroying before creating, updating
// or creating, etc. is all handled by the framework. The plugin author
// only needs to implement a configuration schema and the CRUD operations and
// everything else is meant to just work.
//
// A good starting point is to view the Provider structure.
package schema
import (
@ -24,8 +35,22 @@ const (
)
// Schema is used to describe the structure of a value.
//
// Read the documentation of the struct elements for important details.
type Schema struct {
// Type is the type of the value and must be one of the ValueType values.
//
// This type not only determines what type is expected/valid in configuring
// this value, but also what type is returned when ResourceData.Get is
// called. The types returned by Get are:
//
// TypeBool - bool
// TypeInt - int
// TypeString - string
// TypeList - []interface{}
// TypeMap - map[string]interface{}
// TypeSet - *schema.Set
//
Type ValueType
// If one of these is set, then this item can come from the configuration.
@ -70,6 +95,8 @@ type Schema struct {
// ComputedWhen is a set of queries on the configuration. Whenever any
// of these things is changed, it will require a recompute (this requires
// that Computed is set to true).
//
// NOTE: This currently does not work.
ComputedWhen []string
}