Merge pull request #16588 from hashicorp/f-panic-on-invalid-rd-set

helper/schema: Opt-in panic on invalid ResourceData.Set
This commit is contained in:
Radek Simko 2017-11-08 19:17:46 +00:00 committed by GitHub
commit 2974d63e75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 9 deletions

View File

@ -49,7 +49,6 @@ func testResource() *schema.Resource {
"computed_read_only": { "computed_read_only": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
ForceNew: true,
}, },
"computed_from_required": { "computed_from_required": {
Type: schema.TypeString, Type: schema.TypeString,

View File

@ -47,7 +47,7 @@ func testResourceGH12183() *schema.Resource {
func testResourceCreate_gh12183(d *schema.ResourceData, meta interface{}) error { func testResourceCreate_gh12183(d *schema.ResourceData, meta interface{}) error {
d.SetId("testId") d.SetId("testId")
return testResourceRead(d, meta) return testResourceRead_gh12183(d, meta)
} }
func testResourceRead_gh12183(d *schema.ResourceData, meta interface{}) error { func testResourceRead_gh12183(d *schema.ResourceData, meta interface{}) error {

View File

@ -35,6 +35,8 @@ type ResourceData struct {
partialMap map[string]struct{} partialMap map[string]struct{}
once sync.Once once sync.Once
isNew bool isNew bool
panicOnError bool
} }
// getResult is the internal structure that is generated when a Get // getResult is the internal structure that is generated when a Get
@ -184,7 +186,11 @@ func (d *ResourceData) Set(key string, value interface{}) error {
} }
} }
return d.setWriter.WriteField(strings.Split(key, "."), value) err := d.setWriter.WriteField(strings.Split(key, "."), value)
if err != nil && d.panicOnError {
panic(err)
}
return err
} }
// SetPartial adds the key to the final state output while // SetPartial adds the key to the final state output while

View File

@ -3,6 +3,7 @@ package schema
import ( import (
"fmt" "fmt"
"math" "math"
"os"
"reflect" "reflect"
"testing" "testing"
"time" "time"
@ -2055,6 +2056,10 @@ func TestResourceDataSet(t *testing.T) {
}, },
} }
oldEnv := os.Getenv(PanicOnErr)
os.Setenv(PanicOnErr, "")
defer os.Setenv(PanicOnErr, oldEnv)
for i, tc := range cases { for i, tc := range cases {
d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff) d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
if err != nil { if err != nil {

View File

@ -25,6 +25,9 @@ import (
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
) )
// Name of ENV variable which (if not empty) prefers panic over error
const PanicOnErr = "TF_SCHEMA_PANIC_ON_ERROR"
// type used for schema package context keys // type used for schema package context keys
type contextKey string type contextKey string
@ -358,6 +361,13 @@ func (s *Schema) finalizeDiff(
// schemaMap is a wrapper that adds nice functions on top of schemas. // schemaMap is a wrapper that adds nice functions on top of schemas.
type schemaMap map[string]*Schema type schemaMap map[string]*Schema
func (m schemaMap) panicOnError() bool {
if os.Getenv(PanicOnErr) != "" {
return true
}
return false
}
// Data returns a ResourceData for the given schema, state, and diff. // Data returns a ResourceData for the given schema, state, and diff.
// //
// The diff is optional. // The diff is optional.
@ -365,9 +375,10 @@ func (m schemaMap) Data(
s *terraform.InstanceState, s *terraform.InstanceState,
d *terraform.InstanceDiff) (*ResourceData, error) { d *terraform.InstanceDiff) (*ResourceData, error) {
return &ResourceData{ return &ResourceData{
schema: m, schema: m,
state: s, state: s,
diff: d, diff: d,
panicOnError: m.panicOnError(),
}, nil }, nil
} }
@ -397,9 +408,10 @@ func (m schemaMap) Diff(
} }
d := &ResourceData{ d := &ResourceData{
schema: m, schema: m,
state: s, state: s,
config: c, config: c,
panicOnError: m.panicOnError(),
} }
for k, schema := range m { for k, schema := range m {