github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/states/instance_object_src.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/internal/addrs"
     8  	"github.com/hashicorp/terraform/internal/configs/hcl2shim"
     9  )
    10  
    11  // ResourceInstanceObjectSrc is a not-fully-decoded version of
    12  // ResourceInstanceObject. Decoding of it can be completed by first handling
    13  // any schema migration steps to get to the latest schema version and then
    14  // calling method Decode with the implied type of the latest schema.
    15  type ResourceInstanceObjectSrc struct {
    16  	// SchemaVersion is the resource-type-specific schema version number that
    17  	// was current when either AttrsJSON or AttrsFlat was encoded. Migration
    18  	// steps are required if this is less than the current version number
    19  	// reported by the corresponding provider.
    20  	SchemaVersion uint64
    21  
    22  	// AttrsJSON is a JSON-encoded representation of the object attributes,
    23  	// encoding the value (of the object type implied by the associated resource
    24  	// type schema) that represents this remote object in Terraform Language
    25  	// expressions, and is compared with configuration when producing a diff.
    26  	//
    27  	// This is retained in JSON format here because it may require preprocessing
    28  	// before decoding if, for example, the stored attributes are for an older
    29  	// schema version which the provider must upgrade before use. If the
    30  	// version is current, it is valid to simply decode this using the
    31  	// type implied by the current schema, without the need for the provider
    32  	// to perform an upgrade first.
    33  	//
    34  	// When writing a ResourceInstanceObject into the state, AttrsJSON should
    35  	// always be conformant to the current schema version and the current
    36  	// schema version should be recorded in the SchemaVersion field.
    37  	AttrsJSON []byte
    38  
    39  	// AttrsFlat is a legacy form of attributes used in older state file
    40  	// formats, and in the new state format for objects that haven't yet been
    41  	// upgraded. This attribute is mutually exclusive with Attrs: for any
    42  	// ResourceInstanceObject, only one of these attributes may be populated
    43  	// and the other must be nil.
    44  	//
    45  	// An instance object with this field populated should be upgraded to use
    46  	// Attrs at the earliest opportunity, since this legacy flatmap-based
    47  	// format will be phased out over time. AttrsFlat should not be used when
    48  	// writing new or updated objects to state; instead, callers must follow
    49  	// the recommendations in the AttrsJSON documentation above.
    50  	AttrsFlat map[string]string
    51  
    52  	// AttrSensitivePaths is an array of paths to mark as sensitive coming out of
    53  	// state, or to save as sensitive paths when saving state
    54  	AttrSensitivePaths []cty.PathValueMarks
    55  
    56  	// These fields all correspond to the fields of the same name on
    57  	// ResourceInstanceObject.
    58  	Private             []byte
    59  	Status              ObjectStatus
    60  	Dependencies        []addrs.ConfigResource
    61  	CreateBeforeDestroy bool
    62  }
    63  
    64  // Decode unmarshals the raw representation of the object attributes. Pass the
    65  // implied type of the corresponding resource type schema for correct operation.
    66  //
    67  // Before calling Decode, the caller must check that the SchemaVersion field
    68  // exactly equals the version number of the schema whose implied type is being
    69  // passed, or else the result is undefined.
    70  //
    71  // The returned object may share internal references with the receiver and
    72  // so the caller must not mutate the receiver any further once once this
    73  // method is called.
    74  func (os *ResourceInstanceObjectSrc) Decode(ty cty.Type) (*ResourceInstanceObject, error) {
    75  	var val cty.Value
    76  	var err error
    77  	if os.AttrsFlat != nil {
    78  		// Legacy mode. We'll do our best to unpick this from the flatmap.
    79  		val, err = hcl2shim.HCL2ValueFromFlatmap(os.AttrsFlat, ty)
    80  		if err != nil {
    81  			return nil, err
    82  		}
    83  	} else {
    84  		val, err = ctyjson.Unmarshal(os.AttrsJSON, ty)
    85  		// Mark the value with paths if applicable
    86  		if os.AttrSensitivePaths != nil {
    87  			val = val.MarkWithPaths(os.AttrSensitivePaths)
    88  		}
    89  		if err != nil {
    90  			return nil, err
    91  		}
    92  	}
    93  
    94  	return &ResourceInstanceObject{
    95  		Value:               val,
    96  		Status:              os.Status,
    97  		Dependencies:        os.Dependencies,
    98  		Private:             os.Private,
    99  		CreateBeforeDestroy: os.CreateBeforeDestroy,
   100  	}, nil
   101  }
   102  
   103  // CompleteUpgrade creates a new ResourceInstanceObjectSrc by copying the
   104  // metadata from the receiver and writing in the given new schema version
   105  // and attribute value that are presumed to have resulted from upgrading
   106  // from an older schema version.
   107  func (os *ResourceInstanceObjectSrc) CompleteUpgrade(newAttrs cty.Value, newType cty.Type, newSchemaVersion uint64) (*ResourceInstanceObjectSrc, error) {
   108  	new := os.DeepCopy()
   109  	new.AttrsFlat = nil // We always use JSON after an upgrade, even if the source used flatmap
   110  
   111  	// This is the same principle as ResourceInstanceObject.Encode, but
   112  	// avoiding a decode/re-encode cycle because we don't have type info
   113  	// available for the "old" attributes.
   114  	newAttrs = cty.UnknownAsNull(newAttrs)
   115  	src, err := ctyjson.Marshal(newAttrs, newType)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	new.AttrsJSON = src
   121  	new.SchemaVersion = newSchemaVersion
   122  	return new, nil
   123  }