states: object Private data is []byte, not cty.Value

We're going to allow the provider to encode whatever it wants in here, so
a provider can use whatever is most convenient for its implementation
language and to avoid some of the bugs we saw with the prior model where
the forced round-trip through JSON and back into interface{} would cause
some loss of fidelity, leading to bugs.
This commit is contained in:
Martin Atkins 2018-08-17 16:11:07 -07:00
parent 08a8834882
commit fb57801dfe
7 changed files with 26 additions and 44 deletions

View File

@ -18,7 +18,7 @@ type ImportedObject struct {
// Private corresponds to the field of the same name on
// ResourceInstanceObject, where the provider can record private data that
// will be available for future operations.
Private cty.Value
Private []byte
}
// AsInstanceObject converts the receiving ImportedObject into a

View File

@ -23,7 +23,7 @@ type ResourceInstanceObject struct {
// last created or updated. Terraform Core does not use this value in
// any way and it is not exposed anywhere in the user interface, so
// a provider can use it for retaining any necessary private state.
Private cty.Value
Private []byte
// Status represents the "readiness" of the object as of the last time
// it was updated.

View File

@ -51,7 +51,7 @@ type ResourceInstanceObjectSrc struct {
// These fields all correspond to the fields of the same name on
// ResourceInstanceObject.
Private cty.Value
Private []byte
Status ObjectStatus
Dependencies []addrs.Referenceable
}

View File

@ -38,7 +38,9 @@
"triggers.%": "1",
"triggers.index": "0"
},
"meta": {},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
@ -80,7 +82,9 @@
"triggers.woot": "us-west-2",
"triggers.workspace": "default"
},
"meta": {},
"meta": {
"foo": "bar"
},
"tainted": false
},
"deposed": [],

View File

@ -38,7 +38,7 @@
},
"depends_on": ["null_resource.baz"],
"index_key": 0,
"schema_version": 0
"schema_version": 1
},
{
"attributes_flat": {
@ -72,7 +72,8 @@
"triggers.woot": "us-west-2",
"triggers.workspace": "default"
},
"schema_version": 0
"schema_version": 0,
"private": "eyJmb28iOiJiYXIifQ=="
}
]
},

View File

@ -224,12 +224,19 @@ func upgradeInstanceObjectV3ToV4(rsOld *resourceStateV2, isOld *instanceStateV2,
var schemaVersion uint64
migratedSchemaVersion := false
if raw, exists := isOld.Meta["schema_version"]; exists {
if rawStr, ok := raw.(string); ok {
v, err := strconv.ParseUint(rawStr, 10, 64)
switch tv := raw.(type) {
case string:
v, err := strconv.ParseUint(tv, 10, 64)
if err == nil {
schemaVersion = v
migratedSchemaVersion = true
}
case int:
schemaVersion = uint64(tv)
migratedSchemaVersion = true
case float64:
schemaVersion = uint64(tv)
migratedSchemaVersion = true
}
}

View File

@ -7,7 +7,6 @@ import (
"sort"
version "github.com/hashicorp/go-version"
"github.com/zclconf/go-cty/cty"
ctyjson "github.com/zclconf/go-cty/cty/json"
"github.com/hashicorp/terraform/addrs"
@ -178,28 +177,7 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
}
if raw := isV4.PrivateRaw; len(raw) > 0 {
// Private metadata
ty, err := ctyjson.ImpliedType(raw)
if err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Invalid resource instance metadata in state",
fmt.Sprintf("Instance %s has invalid private metadata: %s.", instAddr.Absolute(moduleAddr), err),
))
continue
}
val, err := ctyjson.Unmarshal(raw, ty)
if err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Invalid resource instance metadata in state",
fmt.Sprintf("Instance %s has invalid private metadata: %s.", instAddr.Absolute(moduleAddr), err),
))
continue
}
obj.Private = val
obj.Private = raw
}
{
@ -475,17 +453,9 @@ func appendInstanceObjectStateV4(rs *states.Resource, is *states.ResourceInstanc
))
}
var privateRaw json.RawMessage
if obj.Private != cty.NilVal {
var err error
privateRaw, err = ctyjson.Marshal(obj.Private, obj.Private.Type())
if err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to serialize resource instance in state",
fmt.Sprintf("Failed to serialize instance %s private metadata: %s.", rs.Addr.Instance(key), err),
))
}
var privateRaw []byte
if len(obj.Private) > 0 {
privateRaw = obj.Private
}
deps := make([]string, len(obj.Dependencies))
@ -565,7 +535,7 @@ type instanceObjectStateV4 struct {
AttributesRaw json.RawMessage `json:"attributes,omitempty"`
AttributesFlat map[string]string `json:"attributes_flat,omitempty"`
PrivateRaw json.RawMessage `json:"private,omitempty"`
PrivateRaw []byte `json:"private,omitempty"`
Dependencies []string `json:"depends_on,omitempty"`
}