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