github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/states/statefile/version2.go (about)

     1  package statefile
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags"
     8  )
     9  
    10  func readStateV2(src []byte) (*File, tfdiags.Diagnostics) {
    11  	var diags tfdiags.Diagnostics
    12  	sV2 := &stateV2{}
    13  	err := json.Unmarshal(src, sV2)
    14  	if err != nil {
    15  		diags = diags.Append(jsonUnmarshalDiags(err))
    16  		return nil, diags
    17  	}
    18  
    19  	file, prepDiags := prepareStateV2(sV2)
    20  	diags = diags.Append(prepDiags)
    21  	return file, diags
    22  }
    23  
    24  func prepareStateV2(sV2 *stateV2) (*File, tfdiags.Diagnostics) {
    25  	var diags tfdiags.Diagnostics
    26  	sV3, err := upgradeStateV2ToV3(sV2)
    27  	if err != nil {
    28  		diags = diags.Append(tfdiags.Sourceless(
    29  			tfdiags.Error,
    30  			upgradeFailed,
    31  			fmt.Sprintf("Error upgrading state file format from version 2 to version 3: %s.", err),
    32  		))
    33  		return nil, diags
    34  	}
    35  
    36  	file, prepDiags := prepareStateV3(sV3)
    37  	diags = diags.Append(prepDiags)
    38  	return file, diags
    39  }
    40  
    41  // stateV2 is a representation of the legacy JSON state format version 2.
    42  //
    43  // It is only used to read version 2 JSON files prior to upgrading them to
    44  // the current format.
    45  type stateV2 struct {
    46  	// Version is the state file protocol version.
    47  	Version int `json:"version"`
    48  
    49  	// TFVersion is the version of Terraform that wrote this state.
    50  	TFVersion string `json:"terraform_version,omitempty"`
    51  
    52  	// Serial is incremented on any operation that modifies
    53  	// the State file. It is used to detect potentially conflicting
    54  	// updates.
    55  	Serial int64 `json:"serial"`
    56  
    57  	// Lineage is set when a new, blank state is created and then
    58  	// never updated. This allows us to determine whether the serials
    59  	// of two states can be meaningfully compared.
    60  	// Apart from the guarantee that collisions between two lineages
    61  	// are very unlikely, this value is opaque and external callers
    62  	// should only compare lineage strings byte-for-byte for equality.
    63  	Lineage string `json:"lineage"`
    64  
    65  	// Remote is used to track the metadata required to
    66  	// pull and push state files from a remote storage endpoint.
    67  	Remote *remoteStateV2 `json:"remote,omitempty"`
    68  
    69  	// Backend tracks the configuration for the backend in use with
    70  	// this state. This is used to track any changes in the backend
    71  	// configuration.
    72  	Backend *backendStateV2 `json:"backend,omitempty"`
    73  
    74  	// Modules contains all the modules in a breadth-first order
    75  	Modules []*moduleStateV2 `json:"modules"`
    76  }
    77  
    78  type remoteStateV2 struct {
    79  	// Type controls the client we use for the remote state
    80  	Type string `json:"type"`
    81  
    82  	// Config is used to store arbitrary configuration that
    83  	// is type specific
    84  	Config map[string]string `json:"config"`
    85  }
    86  
    87  type outputStateV2 struct {
    88  	// Sensitive describes whether the output is considered sensitive,
    89  	// which may lead to masking the value on screen in some cases.
    90  	Sensitive bool `json:"sensitive"`
    91  	// Type describes the structure of Value. Valid values are "string",
    92  	// "map" and "list"
    93  	Type string `json:"type"`
    94  	// Value contains the value of the output, in the structure described
    95  	// by the Type field.
    96  	Value interface{} `json:"value"`
    97  }
    98  
    99  type moduleStateV2 struct {
   100  	// Path is the import path from the root module. Modules imports are
   101  	// always disjoint, so the path represents amodule tree
   102  	Path []string `json:"path"`
   103  
   104  	// Locals are kept only transiently in-memory, because we can always
   105  	// re-compute them.
   106  	Locals map[string]interface{} `json:"-"`
   107  
   108  	// Outputs declared by the module and maintained for each module
   109  	// even though only the root module technically needs to be kept.
   110  	// This allows operators to inspect values at the boundaries.
   111  	Outputs map[string]*outputStateV2 `json:"outputs"`
   112  
   113  	// Resources is a mapping of the logically named resource to
   114  	// the state of the resource. Each resource may actually have
   115  	// N instances underneath, although a user only needs to think
   116  	// about the 1:1 case.
   117  	Resources map[string]*resourceStateV2 `json:"resources"`
   118  
   119  	// Dependencies are a list of things that this module relies on
   120  	// existing to remain intact. For example: an module may depend
   121  	// on a VPC ID given by an aws_vpc resource.
   122  	//
   123  	// Terraform uses this information to build valid destruction
   124  	// orders and to warn the user if they're destroying a module that
   125  	// another resource depends on.
   126  	//
   127  	// Things can be put into this list that may not be managed by
   128  	// Terraform. If Terraform doesn't find a matching ID in the
   129  	// overall state, then it assumes it isn't managed and doesn't
   130  	// worry about it.
   131  	Dependencies []string `json:"depends_on"`
   132  }
   133  
   134  type resourceStateV2 struct {
   135  	// This is filled in and managed by Terraform, and is the resource
   136  	// type itself such as "mycloud_instance". If a resource provider sets
   137  	// this value, it won't be persisted.
   138  	Type string `json:"type"`
   139  
   140  	// Dependencies are a list of things that this resource relies on
   141  	// existing to remain intact. For example: an AWS instance might
   142  	// depend on a subnet (which itself might depend on a VPC, and so
   143  	// on).
   144  	//
   145  	// Terraform uses this information to build valid destruction
   146  	// orders and to warn the user if they're destroying a resource that
   147  	// another resource depends on.
   148  	//
   149  	// Things can be put into this list that may not be managed by
   150  	// Terraform. If Terraform doesn't find a matching ID in the
   151  	// overall state, then it assumes it isn't managed and doesn't
   152  	// worry about it.
   153  	Dependencies []string `json:"depends_on"`
   154  
   155  	// Primary is the current active instance for this resource.
   156  	// It can be replaced but only after a successful creation.
   157  	// This is the instances on which providers will act.
   158  	Primary *instanceStateV2 `json:"primary"`
   159  
   160  	// Deposed is used in the mechanics of CreateBeforeDestroy: the existing
   161  	// Primary is Deposed to get it out of the way for the replacement Primary to
   162  	// be created by Apply. If the replacement Primary creates successfully, the
   163  	// Deposed instance is cleaned up.
   164  	//
   165  	// If there were problems creating the replacement Primary, the Deposed
   166  	// instance and the (now tainted) replacement Primary will be swapped so the
   167  	// tainted replacement will be cleaned up instead.
   168  	//
   169  	// An instance will remain in the Deposed list until it is successfully
   170  	// destroyed and purged.
   171  	Deposed []*instanceStateV2 `json:"deposed"`
   172  
   173  	// Provider is used when a resource is connected to a provider with an alias.
   174  	// If this string is empty, the resource is connected to the default provider,
   175  	// e.g. "aws_instance" goes with the "aws" provider.
   176  	// If the resource block contained a "provider" key, that value will be set here.
   177  	Provider string `json:"provider"`
   178  }
   179  
   180  type instanceStateV2 struct {
   181  	// A unique ID for this resource. This is opaque to Terraform
   182  	// and is only meant as a lookup mechanism for the providers.
   183  	ID string `json:"id"`
   184  
   185  	// Attributes are basic information about the resource. Any keys here
   186  	// are accessible in variable format within Terraform configurations:
   187  	// ${resourcetype.name.attribute}.
   188  	Attributes map[string]string `json:"attributes"`
   189  
   190  	// Meta is a simple K/V map that is persisted to the State but otherwise
   191  	// ignored by Terraform core. It's meant to be used for accounting by
   192  	// external client code. The value here must only contain Go primitives
   193  	// and collections.
   194  	Meta map[string]interface{} `json:"meta"`
   195  
   196  	// Tainted is used to mark a resource for recreation.
   197  	Tainted bool `json:"tainted"`
   198  }
   199  
   200  type backendStateV2 struct {
   201  	Type      string          `json:"type"`   // Backend type
   202  	ConfigRaw json.RawMessage `json:"config"` // Backend raw config
   203  	Hash      uint64          `json:"hash"`   // Hash of portion of configuration from config files
   204  }