2014-08-13 23:23:22 +02:00
|
|
|
package schema
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2014-08-16 01:32:43 +02:00
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
2014-08-13 23:23:22 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// The functions below are the CRUD function types for a Resource.
|
|
|
|
type CreateFunc func(*ResourceData) error
|
|
|
|
type ReadFunc func(*ResourceData) error
|
|
|
|
type UpdateFunc func(*ResourceData) error
|
|
|
|
type DeleteFunc func(*ResourceData) error
|
|
|
|
|
|
|
|
// Resource represents a thing in Terraform that has a set of configurable
|
|
|
|
// attributes and generally also has 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 map[string]*Schema
|
|
|
|
|
|
|
|
Create CreateFunc
|
|
|
|
Read ReadFunc
|
|
|
|
Update UpdateFunc
|
|
|
|
Delete DeleteFunc
|
|
|
|
}
|
|
|
|
|
2014-08-16 01:32:43 +02:00
|
|
|
// Diff returns a diff of this resource and is API compatible with the
|
|
|
|
// ResourceProvider interface.
|
|
|
|
func (r *Resource) Diff(
|
|
|
|
s *terraform.ResourceState,
|
|
|
|
c *terraform.ResourceConfig) (*terraform.ResourceDiff, error) {
|
|
|
|
return schemaMap(r.Schema).Diff(s, c)
|
|
|
|
}
|
|
|
|
|
2014-08-16 07:00:16 +02:00
|
|
|
// Validate validates the resource configuration against the schema.
|
|
|
|
func (r *Resource) Validate(c *terraform.ResourceConfig) ([]string, []error) {
|
|
|
|
return schemaMap(r.Schema).Validate(c)
|
|
|
|
}
|
|
|
|
|
2014-08-13 23:23:22 +02:00
|
|
|
// InternalValidate should be called to validate the structure
|
|
|
|
// of the resource.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
func (r *Resource) InternalValidate() error {
|
|
|
|
if r == nil {
|
|
|
|
return errors.New("resource is nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range r.Schema {
|
|
|
|
if v.Type == TypeInvalid {
|
|
|
|
return fmt.Errorf("%s: Type must be specified", k)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v.Optional && v.Required {
|
|
|
|
return fmt.Errorf("%s: Optional or Required must be set, not both", k)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v.Required && v.Computed {
|
|
|
|
return fmt.Errorf("%s: Cannot be both Required and Computed", k)
|
|
|
|
}
|
2014-08-15 08:32:20 +02:00
|
|
|
|
|
|
|
if v.Type == TypeList {
|
|
|
|
if v.Elem == nil {
|
|
|
|
return fmt.Errorf("%s: Elem must be set for lists", k)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch t := v.Elem.(type) {
|
|
|
|
case *Schema:
|
|
|
|
bad := t.Computed || t.Optional || t.Required
|
|
|
|
if bad {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"%s: Elem must have only Type set", k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-13 23:23:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|