helper/schema: initial work
This commit is contained in:
parent
3e3be5e2a3
commit
01b6b5f48e
|
@ -0,0 +1,56 @@
|
||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package schema
|
||||||
|
|
||||||
|
// ResourceData is used to query and set the attributes of a resource.
|
||||||
|
type ResourceData struct{}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResourceInternalValidate(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
In *Resource
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// No optional and no required
|
||||||
|
{
|
||||||
|
&Resource{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"foo": &Schema{
|
||||||
|
Type: TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Missing Type
|
||||||
|
{
|
||||||
|
&Resource{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"foo": &Schema{
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Required but computed
|
||||||
|
{
|
||||||
|
&Resource{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"foo": &Schema{
|
||||||
|
Type: TypeInt,
|
||||||
|
Required: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Looks good
|
||||||
|
{
|
||||||
|
&Resource{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"foo": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range cases {
|
||||||
|
err := tc.In.InternalValidate()
|
||||||
|
if (err != nil) != tc.Err {
|
||||||
|
t.Fatalf("%d: bad: %s", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package schema
|
||||||
|
|
||||||
|
// ValueType is an enum of the type that can be represented by a schema.
|
||||||
|
type ValueType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeInvalid ValueType = iota
|
||||||
|
TypeBoolean
|
||||||
|
TypeInt
|
||||||
|
TypeString
|
||||||
|
TypeList
|
||||||
|
)
|
||||||
|
|
||||||
|
// Schema is used to describe the structure of a value.
|
||||||
|
type Schema struct {
|
||||||
|
// Type is the type of the value and must be one of the ValueType values.
|
||||||
|
Type ValueType
|
||||||
|
|
||||||
|
// If one of these is set, then this item can come from the configuration.
|
||||||
|
// Both cannot be set. If Optional is set, the value is optional. If
|
||||||
|
// Required is set, the value is required.
|
||||||
|
Optional bool
|
||||||
|
Required bool
|
||||||
|
|
||||||
|
// The fields below relate to diffs: if Computed is true, then the
|
||||||
|
// result of this value is computed (unless specified by config).
|
||||||
|
// If ForceNew is true
|
||||||
|
Computed bool
|
||||||
|
ForceNew bool
|
||||||
|
|
||||||
|
// Elem must be either a *Schema or a *Resource only if the Type is
|
||||||
|
// TypeList, and represents what the element type is. If it is *Schema,
|
||||||
|
// the element type is just a simple value. If it is *Resource, the
|
||||||
|
// element type is a complex structure, potentially with its own lifecycle.
|
||||||
|
Elem interface{}
|
||||||
|
}
|
Loading…
Reference in New Issue