github.com/opentofu/opentofu@v1.7.1/internal/states/statefile/version1_upgrade.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 "fmt" 10 "log" 11 12 "github.com/mitchellh/copystructure" 13 ) 14 15 // upgradeStateV1ToV2 is used to upgrade a V1 state representation 16 // into a V2 state representation 17 func upgradeStateV1ToV2(old *stateV1) (*stateV2, error) { 18 log.Printf("[TRACE] statefile.Read: upgrading format from v1 to v2") 19 if old == nil { 20 return nil, nil 21 } 22 23 remote, err := old.Remote.upgradeToV2() 24 if err != nil { 25 return nil, fmt.Errorf("Error upgrading State V1: %w", err) 26 } 27 28 modules := make([]*moduleStateV2, len(old.Modules)) 29 for i, module := range old.Modules { 30 upgraded, err := module.upgradeToV2() 31 if err != nil { 32 return nil, fmt.Errorf("Error upgrading State V1: %w", err) 33 } 34 modules[i] = upgraded 35 } 36 if len(modules) == 0 { 37 modules = nil 38 } 39 40 newState := &stateV2{ 41 Version: 2, 42 Serial: old.Serial, 43 Remote: remote, 44 Modules: modules, 45 } 46 47 return newState, nil 48 } 49 50 func (old *remoteStateV1) upgradeToV2() (*remoteStateV2, error) { 51 if old == nil { 52 return nil, nil 53 } 54 55 config, err := copystructure.Copy(old.Config) 56 if err != nil { 57 return nil, fmt.Errorf("Error upgrading RemoteState V1: %w", err) 58 } 59 60 return &remoteStateV2{ 61 Type: old.Type, 62 Config: config.(map[string]string), 63 }, nil 64 } 65 66 func (old *moduleStateV1) upgradeToV2() (*moduleStateV2, error) { 67 if old == nil { 68 return nil, nil 69 } 70 71 pathRaw, err := copystructure.Copy(old.Path) 72 if err != nil { 73 return nil, fmt.Errorf("Error upgrading ModuleState V1: %w", err) 74 } 75 path, ok := pathRaw.([]string) 76 if !ok { 77 return nil, fmt.Errorf("Error upgrading ModuleState V1: path is not a list of strings") 78 } 79 if len(path) == 0 { 80 // We found some V1 states with a nil path. Assume root. 81 path = []string{"root"} 82 } 83 84 // Outputs needs upgrading to use the new structure 85 outputs := make(map[string]*outputStateV2) 86 for key, output := range old.Outputs { 87 outputs[key] = &outputStateV2{ 88 Type: "string", 89 Value: output, 90 Sensitive: false, 91 } 92 } 93 94 resources := make(map[string]*resourceStateV2) 95 for key, oldResource := range old.Resources { 96 upgraded, err := oldResource.upgradeToV2() 97 if err != nil { 98 return nil, fmt.Errorf("Error upgrading ModuleState V1: %w", err) 99 } 100 resources[key] = upgraded 101 } 102 103 dependencies, err := copystructure.Copy(old.Dependencies) 104 if err != nil { 105 return nil, fmt.Errorf("Error upgrading ModuleState V1: %w", err) 106 } 107 108 return &moduleStateV2{ 109 Path: path, 110 Outputs: outputs, 111 Resources: resources, 112 Dependencies: dependencies.([]string), 113 }, nil 114 } 115 116 func (old *resourceStateV1) upgradeToV2() (*resourceStateV2, error) { 117 if old == nil { 118 return nil, nil 119 } 120 121 dependencies, err := copystructure.Copy(old.Dependencies) 122 if err != nil { 123 return nil, fmt.Errorf("Error upgrading ResourceState V1: %w", err) 124 } 125 126 primary, err := old.Primary.upgradeToV2() 127 if err != nil { 128 return nil, fmt.Errorf("Error upgrading ResourceState V1: %w", err) 129 } 130 131 deposed := make([]*instanceStateV2, len(old.Deposed)) 132 for i, v := range old.Deposed { 133 upgraded, err := v.upgradeToV2() 134 if err != nil { 135 return nil, fmt.Errorf("Error upgrading ResourceState V1: %w", err) 136 } 137 deposed[i] = upgraded 138 } 139 if len(deposed) == 0 { 140 deposed = nil 141 } 142 143 return &resourceStateV2{ 144 Type: old.Type, 145 Dependencies: dependencies.([]string), 146 Primary: primary, 147 Deposed: deposed, 148 Provider: old.Provider, 149 }, nil 150 } 151 152 func (old *instanceStateV1) upgradeToV2() (*instanceStateV2, error) { 153 if old == nil { 154 return nil, nil 155 } 156 157 attributes, err := copystructure.Copy(old.Attributes) 158 if err != nil { 159 return nil, fmt.Errorf("Error upgrading InstanceState V1: %w", err) 160 } 161 162 meta, err := copystructure.Copy(old.Meta) 163 if err != nil { 164 return nil, fmt.Errorf("Error upgrading InstanceState V1: %w", err) 165 } 166 167 newMeta := make(map[string]interface{}) 168 for k, v := range meta.(map[string]string) { 169 newMeta[k] = v 170 } 171 172 return &instanceStateV2{ 173 ID: old.ID, 174 Attributes: attributes.(map[string]string), 175 Meta: newMeta, 176 }, nil 177 }