github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/states/statefile/version1.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package statefile 5 6 import ( 7 "encoding/json" 8 "fmt" 9 10 "github.com/terramate-io/tf/tfdiags" 11 ) 12 13 func readStateV1(src []byte) (*File, tfdiags.Diagnostics) { 14 var diags tfdiags.Diagnostics 15 sV1 := &stateV1{} 16 err := json.Unmarshal(src, sV1) 17 if err != nil { 18 diags = diags.Append(jsonUnmarshalDiags(err)) 19 return nil, diags 20 } 21 22 file, prepDiags := prepareStateV1(sV1) 23 diags = diags.Append(prepDiags) 24 return file, diags 25 } 26 27 func prepareStateV1(sV1 *stateV1) (*File, tfdiags.Diagnostics) { 28 var diags tfdiags.Diagnostics 29 sV2, err := upgradeStateV1ToV2(sV1) 30 if err != nil { 31 diags = diags.Append(tfdiags.Sourceless( 32 tfdiags.Error, 33 upgradeFailed, 34 fmt.Sprintf("Error upgrading state file format from version 1 to version 2: %s.", err), 35 )) 36 return nil, diags 37 } 38 39 file, prepDiags := prepareStateV2(sV2) 40 diags = diags.Append(prepDiags) 41 return file, diags 42 } 43 44 // stateV1 is a representation of the legacy JSON state format version 1. 45 // 46 // It is only used to read version 1 JSON files prior to upgrading them to 47 // the current format. 48 type stateV1 struct { 49 // Version is the protocol version. "1" for a StateV1. 50 Version int `json:"version"` 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 // Remote is used to track the metadata required to 58 // pull and push state files from a remote storage endpoint. 59 Remote *remoteStateV1 `json:"remote,omitempty"` 60 61 // Modules contains all the modules in a breadth-first order 62 Modules []*moduleStateV1 `json:"modules"` 63 } 64 65 type remoteStateV1 struct { 66 // Type controls the client we use for the remote state 67 Type string `json:"type"` 68 69 // Config is used to store arbitrary configuration that 70 // is type specific 71 Config map[string]string `json:"config"` 72 } 73 74 type moduleStateV1 struct { 75 // Path is the import path from the root module. Modules imports are 76 // always disjoint, so the path represents amodule tree 77 Path []string `json:"path"` 78 79 // Outputs declared by the module and maintained for each module 80 // even though only the root module technically needs to be kept. 81 // This allows operators to inspect values at the boundaries. 82 Outputs map[string]string `json:"outputs"` 83 84 // Resources is a mapping of the logically named resource to 85 // the state of the resource. Each resource may actually have 86 // N instances underneath, although a user only needs to think 87 // about the 1:1 case. 88 Resources map[string]*resourceStateV1 `json:"resources"` 89 90 // Dependencies are a list of things that this module relies on 91 // existing to remain intact. For example: an module may depend 92 // on a VPC ID given by an aws_vpc resource. 93 // 94 // Terraform uses this information to build valid destruction 95 // orders and to warn the user if they're destroying a module that 96 // another resource depends on. 97 // 98 // Things can be put into this list that may not be managed by 99 // Terraform. If Terraform doesn't find a matching ID in the 100 // overall state, then it assumes it isn't managed and doesn't 101 // worry about it. 102 Dependencies []string `json:"depends_on,omitempty"` 103 } 104 105 type resourceStateV1 struct { 106 // This is filled in and managed by Terraform, and is the resource 107 // type itself such as "mycloud_instance". If a resource provider sets 108 // this value, it won't be persisted. 109 Type string `json:"type"` 110 111 // Dependencies are a list of things that this resource relies on 112 // existing to remain intact. For example: an AWS instance might 113 // depend on a subnet (which itself might depend on a VPC, and so 114 // on). 115 // 116 // Terraform uses this information to build valid destruction 117 // orders and to warn the user if they're destroying a resource that 118 // another resource depends on. 119 // 120 // Things can be put into this list that may not be managed by 121 // Terraform. If Terraform doesn't find a matching ID in the 122 // overall state, then it assumes it isn't managed and doesn't 123 // worry about it. 124 Dependencies []string `json:"depends_on,omitempty"` 125 126 // Primary is the current active instance for this resource. 127 // It can be replaced but only after a successful creation. 128 // This is the instances on which providers will act. 129 Primary *instanceStateV1 `json:"primary"` 130 131 // Tainted is used to track any underlying instances that 132 // have been created but are in a bad or unknown state and 133 // need to be cleaned up subsequently. In the 134 // standard case, there is only at most a single instance. 135 // However, in pathological cases, it is possible for the number 136 // of instances to accumulate. 137 Tainted []*instanceStateV1 `json:"tainted,omitempty"` 138 139 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 140 // Primary is Deposed to get it out of the way for the replacement Primary to 141 // be created by Apply. If the replacement Primary creates successfully, the 142 // Deposed instance is cleaned up. If there were problems creating the 143 // replacement, the instance remains in the Deposed list so it can be 144 // destroyed in a future run. Functionally, Deposed instances are very 145 // similar to Tainted instances in that Terraform is only tracking them in 146 // order to remember to destroy them. 147 Deposed []*instanceStateV1 `json:"deposed,omitempty"` 148 149 // Provider is used when a resource is connected to a provider with an alias. 150 // If this string is empty, the resource is connected to the default provider, 151 // e.g. "aws_instance" goes with the "aws" provider. 152 // If the resource block contained a "provider" key, that value will be set here. 153 Provider string `json:"provider,omitempty"` 154 } 155 156 type instanceStateV1 struct { 157 // A unique ID for this resource. This is opaque to Terraform 158 // and is only meant as a lookup mechanism for the providers. 159 ID string `json:"id"` 160 161 // Attributes are basic information about the resource. Any keys here 162 // are accessible in variable format within Terraform configurations: 163 // ${resourcetype.name.attribute}. 164 Attributes map[string]string `json:"attributes,omitempty"` 165 166 // Meta is a simple K/V map that is persisted to the State but otherwise 167 // ignored by Terraform core. It's meant to be used for accounting by 168 // external client code. 169 Meta map[string]string `json:"meta,omitempty"` 170 }