github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/states/instance_object.go (about) 1 package states 2 3 import ( 4 "github.com/zclconf/go-cty/cty" 5 ctyjson "github.com/zclconf/go-cty/cty/json" 6 7 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 8 ) 9 10 // ResourceInstanceObject is the local representation of a specific remote 11 // object associated with a resource instance. In practice not all remote 12 // objects are actually remote in the sense of being accessed over the network, 13 // but this is the most common case. 14 // 15 // It is not valid to mutate a ResourceInstanceObject once it has been created. 16 // Instead, create a new object and replace the existing one. 17 type ResourceInstanceObject struct { 18 // Value is the object-typed value representing the remote object within 19 // Terraform. 20 Value cty.Value 21 22 // Private is an opaque value set by the provider when this object was 23 // last created or updated. Terraform Core does not use this value in 24 // any way and it is not exposed anywhere in the user interface, so 25 // a provider can use it for retaining any necessary private state. 26 Private []byte 27 28 // Status represents the "readiness" of the object as of the last time 29 // it was updated. 30 Status ObjectStatus 31 32 // Dependencies is a set of other addresses in the same module which 33 // this instance depended on when the given attributes were evaluated. 34 // This is used to construct the dependency relationships for an object 35 // whose configuration is no longer available, such as if it has been 36 // removed from configuration altogether, or is now deposed. 37 Dependencies []addrs.Referenceable 38 } 39 40 // ObjectStatus represents the status of a RemoteObject. 41 type ObjectStatus rune 42 43 //go:generate go run golang.org/x/tools/cmd/stringer -type ObjectStatus 44 45 const ( 46 // ObjectReady is an object status for an object that is ready to use. 47 ObjectReady ObjectStatus = 'R' 48 49 // ObjectTainted is an object status representing an object that is in 50 // an unrecoverable bad state due to a partial failure during a create, 51 // update, or delete operation. Since it cannot be moved into the 52 // ObjectRead state, a tainted object must be replaced. 53 ObjectTainted ObjectStatus = 'T' 54 55 // ObjectPlanned is a special object status used only for the transient 56 // placeholder objects we place into state during the refresh and plan 57 // walks to stand in for objects that will be created during apply. 58 // 59 // Any object of this status must have a corresponding change recorded 60 // in the current plan, whose value must then be used in preference to 61 // the value stored in state when evaluating expressions. A planned 62 // object stored in state will be incomplete if any of its attributes are 63 // not yet known, and the plan must be consulted in order to "see" those 64 // unknown values, because the state is not able to represent them. 65 ObjectPlanned ObjectStatus = 'P' 66 ) 67 68 // Encode marshals the value within the receiver to produce a 69 // ResourceInstanceObjectSrc ready to be written to a state file. 70 // 71 // The given type must be the implied type of the resource type schema, and 72 // the given value must conform to it. It is important to pass the schema 73 // type and not the object's own type so that dynamically-typed attributes 74 // will be stored correctly. The caller must also provide the version number 75 // of the schema that the given type was derived from, which will be recorded 76 // in the source object so it can be used to detect when schema migration is 77 // required on read. 78 // 79 // The returned object may share internal references with the receiver and 80 // so the caller must not mutate the receiver any further once once this 81 // method is called. 82 func (o *ResourceInstanceObject) Encode(ty cty.Type, schemaVersion uint64) (*ResourceInstanceObjectSrc, error) { 83 // Our state serialization can't represent unknown values, so we convert 84 // them to nulls here. This is lossy, but nobody should be writing unknown 85 // values here and expecting to get them out again later. 86 // 87 // We get unknown values here while we're building out a "planned state" 88 // during the plan phase, but the value stored in the plan takes precedence 89 // for expression evaluation. The apply step should never produce unknown 90 // values, but if it does it's the responsibility of the caller to detect 91 // and raise an error about that. 92 val := cty.UnknownAsNull(o.Value) 93 94 src, err := ctyjson.Marshal(val, ty) 95 if err != nil { 96 return nil, err 97 } 98 99 return &ResourceInstanceObjectSrc{ 100 SchemaVersion: schemaVersion, 101 AttrsJSON: src, 102 Private: o.Private, 103 Status: o.Status, 104 Dependencies: o.Dependencies, 105 }, nil 106 } 107 108 // AsTainted returns a deep copy of the receiver with the status updated to 109 // ObjectTainted. 110 func (o *ResourceInstanceObject) AsTainted() *ResourceInstanceObject { 111 if o == nil { 112 // A nil object can't be tainted, but we'll allow this anyway to 113 // avoid a crash, since we presumably intend to eventually record 114 // the object has having been deleted anyway. 115 return nil 116 } 117 ret := o.DeepCopy() 118 ret.Status = ObjectTainted 119 return ret 120 }