core: EvalWriteOutput must convert values to string

Our old state format requires all primitive values to be strings. We were
trying to enforce that before, but this didn't work properly because
gocty does not perform automatic type conversions.

Instead, we now convert to string first and then convert the result into
a native Go string afterwards.
This commit is contained in:
Martin Atkins 2018-05-11 15:44:41 -07:00
parent 6a859f1fe3
commit 54464e3f93
1 changed files with 11 additions and 4 deletions

View File

@ -5,11 +5,13 @@ import (
"log" "log"
"github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty/gocty"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/config/hcl2shim" "github.com/hashicorp/terraform/config/hcl2shim"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
) )
// EvalDeleteOutput is an EvalNode implementation that deletes an output // EvalDeleteOutput is an EvalNode implementation that deletes an output
@ -101,10 +103,15 @@ func (n *EvalWriteOutput) Eval(ctx EvalContext) (interface{}, error) {
// State doesn't currently support null, so we'll save as empty string. // State doesn't currently support null, so we'll save as empty string.
valueTyped = "" valueTyped = ""
default: default:
err := gocty.FromCtyValue(val, &valueTyped) strVal, err := convert.Convert(val, cty.String)
if err != nil { if err != nil {
// Should never happen, because all primitives can convert to string. // Should never happen, because all primitives can convert to string.
return nil, fmt.Errorf("cannot marshal %#v for storage in state: %s", err) return nil, fmt.Errorf("cannot marshal %#v for storage in state: %s", val, err)
}
err = gocty.FromCtyValue(strVal, &valueTyped)
if err != nil {
// Should never happen, because we already converted to string.
return nil, fmt.Errorf("cannot marshal %#v for storage in state: %s", val, err)
} }
} }
mod.Outputs[n.Addr.Name] = &OutputState{ mod.Outputs[n.Addr.Name] = &OutputState{