helper/schema: DefaultFunc for dynamic defaults
/cc @c4milo - This might be useful to you as well.
This commit is contained in:
parent
e8d09da6fa
commit
0250c17d6e
|
@ -64,7 +64,15 @@ type Schema struct {
|
||||||
|
|
||||||
// If this is non-nil, then this will be a default value that is used
|
// If this is non-nil, then this will be a default value that is used
|
||||||
// when this item is not set in the configuration/state.
|
// when this item is not set in the configuration/state.
|
||||||
Default interface{}
|
//
|
||||||
|
// DefaultFunc can be specified if you want a dynamic default value.
|
||||||
|
// Only one of Default or DefaultFunc can be set.
|
||||||
|
//
|
||||||
|
// If Required is true above, then Default cannot be set. DefaultFunc
|
||||||
|
// can be set with Required. If the DefaultFunc returns nil, then there
|
||||||
|
// will no default and the user will be asked to fill it in.
|
||||||
|
Default interface{}
|
||||||
|
DefaultFunc SchemaDefaultFunc
|
||||||
|
|
||||||
// The fields below relate to diffs.
|
// The fields below relate to diffs.
|
||||||
//
|
//
|
||||||
|
@ -104,6 +112,10 @@ type Schema struct {
|
||||||
ComputedWhen []string
|
ComputedWhen []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SchemaDefaultFunc is a function called to return a default value for
|
||||||
|
// a field.
|
||||||
|
type SchemaDefaultFunc func() (interface{}, error)
|
||||||
|
|
||||||
// SchemaSetFunc is a function that must return a unique ID for the given
|
// SchemaSetFunc is a function that must return a unique ID for the given
|
||||||
// element. This unique ID is used to store the element in a hash.
|
// element. This unique ID is used to store the element in a hash.
|
||||||
type SchemaSetFunc func(interface{}) int
|
type SchemaSetFunc func(interface{}) int
|
||||||
|
@ -288,6 +300,10 @@ func (m schemaMap) InternalValidate() error {
|
||||||
return fmt.Errorf("%s: Default must be nil if computed", k)
|
return fmt.Errorf("%s: Default must be nil if computed", k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v.Required && v.Default != nil {
|
||||||
|
return fmt.Errorf("%s: Default cannot be set with Required", k)
|
||||||
|
}
|
||||||
|
|
||||||
if len(v.ComputedWhen) > 0 && !v.Computed {
|
if len(v.ComputedWhen) > 0 && !v.Computed {
|
||||||
return fmt.Errorf("%s: ComputedWhen can only be set with Computed", k)
|
return fmt.Errorf("%s: ComputedWhen can only be set with Computed", k)
|
||||||
}
|
}
|
||||||
|
@ -506,6 +522,13 @@ func (m schemaMap) diffString(
|
||||||
o, n, _ := d.diffChange(k)
|
o, n, _ := d.diffChange(k)
|
||||||
if n == nil {
|
if n == nil {
|
||||||
n = schema.Default
|
n = schema.Default
|
||||||
|
if schema.DefaultFunc != nil {
|
||||||
|
var err error
|
||||||
|
n, err = schema.DefaultFunc()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s, error loading default: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if schema.StateFunc != nil {
|
if schema.StateFunc != nil {
|
||||||
originalN = n
|
originalN = n
|
||||||
|
@ -551,6 +574,18 @@ func (m schemaMap) validate(
|
||||||
schema *Schema,
|
schema *Schema,
|
||||||
c *terraform.ResourceConfig) ([]string, []error) {
|
c *terraform.ResourceConfig) ([]string, []error) {
|
||||||
raw, ok := c.Get(k)
|
raw, ok := c.Get(k)
|
||||||
|
if !ok && schema.DefaultFunc != nil {
|
||||||
|
// We have a dynamic default. Check if we have a value.
|
||||||
|
var err error
|
||||||
|
raw, err = schema.DefaultFunc()
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{fmt.Errorf(
|
||||||
|
"%s, error loading default: %s", k, err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're okay as long as we had a value set
|
||||||
|
ok = raw != nil
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
if schema.Required {
|
if schema.Required {
|
||||||
return nil, []error{fmt.Errorf(
|
return nil, []error{fmt.Errorf(
|
||||||
|
|
|
@ -124,6 +124,64 @@ func TestSchemaMap_Diff(t *testing.T) {
|
||||||
Err: false,
|
Err: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// DefaultFunc, value
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"availability_zone": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Optional: true,
|
||||||
|
DefaultFunc: func() (interface{}, error) {
|
||||||
|
return "foo", nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
State: nil,
|
||||||
|
|
||||||
|
Config: nil,
|
||||||
|
|
||||||
|
Diff: &terraform.ResourceDiff{
|
||||||
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||||
|
"availability_zone": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "",
|
||||||
|
New: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
// DefaultFunc, configuration set
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"availability_zone": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Optional: true,
|
||||||
|
DefaultFunc: func() (interface{}, error) {
|
||||||
|
return "foo", nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
State: nil,
|
||||||
|
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"availability_zone": "bar",
|
||||||
|
},
|
||||||
|
|
||||||
|
Diff: &terraform.ResourceDiff{
|
||||||
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||||
|
"availability_zone": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "",
|
||||||
|
New: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
|
||||||
// String with StateFunc
|
// String with StateFunc
|
||||||
{
|
{
|
||||||
Schema: map[string]*Schema{
|
Schema: map[string]*Schema{
|
||||||
|
@ -1055,6 +1113,19 @@ func TestSchemaMap_InternalValidate(t *testing.T) {
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Required but has default
|
||||||
|
{
|
||||||
|
map[string]*Schema{
|
||||||
|
"foo": &Schema{
|
||||||
|
Type: TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Required: true,
|
||||||
|
Default: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
|
||||||
// List element not set
|
// List element not set
|
||||||
{
|
{
|
||||||
map[string]*Schema{
|
map[string]*Schema{
|
||||||
|
@ -1227,6 +1298,38 @@ func TestSchemaMap_Validate(t *testing.T) {
|
||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Required but has DefaultFunc
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"availability_zone": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Required: true,
|
||||||
|
DefaultFunc: func() (interface{}, error) {
|
||||||
|
return "foo", nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Config: nil,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Required but has DefaultFunc return nil
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"availability_zone": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Required: true,
|
||||||
|
DefaultFunc: func() (interface{}, error) {
|
||||||
|
return nil, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Config: nil,
|
||||||
|
|
||||||
|
Err: true,
|
||||||
|
},
|
||||||
|
|
||||||
// Optional sub-resource
|
// Optional sub-resource
|
||||||
{
|
{
|
||||||
Schema: map[string]*Schema{
|
Schema: map[string]*Schema{
|
||||||
|
|
Loading…
Reference in New Issue