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