github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/states/statefile/version2.go (about)

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