github.com/opentofu/opentofu@v1.7.1/internal/tofumigrate/tofumigrate_test.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 tofumigrate 7 8 import ( 9 "reflect" 10 "testing" 11 12 "github.com/hashicorp/hcl/v2" 13 14 "github.com/opentofu/opentofu/internal/addrs" 15 "github.com/opentofu/opentofu/internal/configs" 16 "github.com/opentofu/opentofu/internal/configs/configload" 17 "github.com/opentofu/opentofu/internal/states" 18 ) 19 20 func TestMigrateStateProviderAddresses(t *testing.T) { 21 loader, close := configload.NewLoaderForTests(t) 22 defer close() 23 24 mustParseInstAddr := func(s string) addrs.AbsResourceInstance { 25 addr, err := addrs.ParseAbsResourceInstanceStr(s) 26 if err != nil { 27 t.Fatal(err) 28 } 29 return addr 30 } 31 32 makeRootProviderAddr := func(s string) addrs.AbsProviderConfig { 33 return addrs.AbsProviderConfig{ 34 Module: addrs.RootModule, 35 Provider: addrs.MustParseProviderSourceString(s), 36 } 37 } 38 39 type args struct { 40 configDir string 41 state *states.State 42 } 43 tests := []struct { 44 name string 45 args args 46 want *states.State 47 }{ 48 { 49 name: "if there are no code references, migrate", 50 args: args{ 51 configDir: "testdata/nomention", 52 state: states.BuildState(func(s *states.SyncState) { 53 s.SetResourceInstanceCurrent( 54 mustParseInstAddr("random_id.example"), 55 &states.ResourceInstanceObjectSrc{ 56 Status: states.ObjectReady, 57 AttrsJSON: []byte(`{}`), 58 }, 59 makeRootProviderAddr("registry.terraform.io/hashicorp/random"), 60 ) 61 s.SetResourceInstanceCurrent( 62 mustParseInstAddr("aws_instance.example"), 63 &states.ResourceInstanceObjectSrc{ 64 Status: states.ObjectReady, 65 AttrsJSON: []byte(`{}`), 66 }, 67 makeRootProviderAddr("registry.terraform.io/hashicorp/aws"), 68 ) 69 }), 70 }, 71 want: states.BuildState(func(s *states.SyncState) { 72 s.SetResourceInstanceCurrent( 73 mustParseInstAddr("random_id.example"), 74 &states.ResourceInstanceObjectSrc{ 75 Status: states.ObjectReady, 76 AttrsJSON: []byte(`{}`), 77 }, 78 makeRootProviderAddr("registry.opentofu.org/hashicorp/random"), 79 ) 80 s.SetResourceInstanceCurrent( 81 mustParseInstAddr("aws_instance.example"), 82 &states.ResourceInstanceObjectSrc{ 83 Status: states.ObjectReady, 84 AttrsJSON: []byte(`{}`), 85 }, 86 makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"), 87 ) 88 }), 89 }, 90 { 91 name: "if there are some full-form references in the code, only migrate the ones not referenced", 92 args: args{ 93 configDir: "testdata/mention", 94 state: states.BuildState(func(s *states.SyncState) { 95 s.SetResourceInstanceCurrent( 96 mustParseInstAddr("random_id.example"), 97 &states.ResourceInstanceObjectSrc{ 98 Status: states.ObjectReady, 99 AttrsJSON: []byte(`{}`), 100 }, 101 makeRootProviderAddr("registry.terraform.io/hashicorp/random"), 102 ) 103 s.SetResourceInstanceCurrent( 104 mustParseInstAddr("aws_instance.example"), 105 &states.ResourceInstanceObjectSrc{ 106 Status: states.ObjectReady, 107 AttrsJSON: []byte(`{}`), 108 }, 109 makeRootProviderAddr("registry.terraform.io/hashicorp/aws"), 110 ) 111 }), 112 }, 113 want: states.BuildState(func(s *states.SyncState) { 114 s.SetResourceInstanceCurrent( 115 mustParseInstAddr("random_id.example"), 116 &states.ResourceInstanceObjectSrc{ 117 Status: states.ObjectReady, 118 AttrsJSON: []byte(`{}`), 119 }, 120 makeRootProviderAddr("registry.opentofu.org/hashicorp/random"), 121 ) 122 s.SetResourceInstanceCurrent( 123 mustParseInstAddr("aws_instance.example"), 124 &states.ResourceInstanceObjectSrc{ 125 Status: states.ObjectReady, 126 AttrsJSON: []byte(`{}`), 127 }, 128 makeRootProviderAddr("registry.terraform.io/hashicorp/aws"), 129 ) 130 }), 131 }, 132 { 133 name: "if the state file contains no legacy references, return statefile unchanged", 134 args: args{ 135 configDir: "testdata/nomention", 136 state: states.BuildState(func(s *states.SyncState) { 137 s.SetResourceInstanceCurrent( 138 mustParseInstAddr("random_id.example"), 139 &states.ResourceInstanceObjectSrc{ 140 Status: states.ObjectReady, 141 AttrsJSON: []byte(`{}`), 142 }, 143 makeRootProviderAddr("registry.opentofu.org/hashicorp/random"), 144 ) 145 s.SetResourceInstanceCurrent( 146 mustParseInstAddr("aws_instance.example"), 147 &states.ResourceInstanceObjectSrc{ 148 Status: states.ObjectReady, 149 AttrsJSON: []byte(`{}`), 150 }, 151 makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"), 152 ) 153 }), 154 }, 155 want: states.BuildState(func(s *states.SyncState) { 156 s.SetResourceInstanceCurrent( 157 mustParseInstAddr("random_id.example"), 158 &states.ResourceInstanceObjectSrc{ 159 Status: states.ObjectReady, 160 AttrsJSON: []byte(`{}`), 161 }, 162 makeRootProviderAddr("registry.opentofu.org/hashicorp/random"), 163 ) 164 s.SetResourceInstanceCurrent( 165 mustParseInstAddr("aws_instance.example"), 166 &states.ResourceInstanceObjectSrc{ 167 Status: states.ObjectReady, 168 AttrsJSON: []byte(`{}`), 169 }, 170 makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"), 171 ) 172 }), 173 }, 174 { 175 name: "if there is no code, migrate", 176 args: args{ 177 configDir: "", 178 state: states.BuildState(func(s *states.SyncState) { 179 s.SetResourceInstanceCurrent( 180 mustParseInstAddr("random_id.example"), 181 &states.ResourceInstanceObjectSrc{ 182 Status: states.ObjectReady, 183 AttrsJSON: []byte(`{}`), 184 }, 185 makeRootProviderAddr("registry.terraform.io/hashicorp/random"), 186 ) 187 s.SetResourceInstanceCurrent( 188 mustParseInstAddr("aws_instance.example"), 189 &states.ResourceInstanceObjectSrc{ 190 Status: states.ObjectReady, 191 AttrsJSON: []byte(`{}`), 192 }, 193 makeRootProviderAddr("registry.terraform.io/hashicorp/aws"), 194 ) 195 }), 196 }, 197 want: states.BuildState(func(s *states.SyncState) { 198 s.SetResourceInstanceCurrent( 199 mustParseInstAddr("random_id.example"), 200 &states.ResourceInstanceObjectSrc{ 201 Status: states.ObjectReady, 202 AttrsJSON: []byte(`{}`), 203 }, 204 makeRootProviderAddr("registry.opentofu.org/hashicorp/random"), 205 ) 206 s.SetResourceInstanceCurrent( 207 mustParseInstAddr("aws_instance.example"), 208 &states.ResourceInstanceObjectSrc{ 209 Status: states.ObjectReady, 210 AttrsJSON: []byte(`{}`), 211 }, 212 makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"), 213 ) 214 }), 215 }, 216 } 217 for _, tt := range tests { 218 t.Run(tt.name, func(t *testing.T) { 219 var cfg *configs.Config 220 if tt.args.configDir != "" { 221 var hclDiags hcl.Diagnostics 222 cfg, hclDiags = loader.LoadConfig(tt.args.configDir) 223 if hclDiags.HasErrors() { 224 t.Fatalf("invalid configuration: %s", hclDiags.Error()) 225 } 226 } 227 228 got, err := MigrateStateProviderAddresses(cfg, tt.args.state) 229 if !reflect.DeepEqual(got, tt.want) { 230 t.Errorf("MigrateStateProviderAddresses() got = %v, want %v", got, tt.want) 231 } 232 if err != nil { 233 t.Errorf("MigrateStateProviderAddresses() err = %v, want %v", err, nil) 234 } 235 }) 236 } 237 }