-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package schema | ||
|
||
// ResourceData is used to query and set the attributes of a resource. | ||
type ResourceData struct{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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{} | ||
} |