github.com/pulumi/terraform@v1.4.0/pkg/addrs/parse_target_test.go (about) 1 package addrs 2 3 import ( 4 "testing" 5 6 "github.com/go-test/deep" 7 "github.com/hashicorp/hcl/v2" 8 "github.com/hashicorp/hcl/v2/hclsyntax" 9 "github.com/pulumi/terraform/pkg/tfdiags" 10 ) 11 12 func TestParseTarget(t *testing.T) { 13 tests := []struct { 14 Input string 15 Want *Target 16 WantErr string 17 }{ 18 { 19 `module.foo`, 20 &Target{ 21 Subject: ModuleInstance{ 22 { 23 Name: "foo", 24 }, 25 }, 26 SourceRange: tfdiags.SourceRange{ 27 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 28 End: tfdiags.SourcePos{Line: 1, Column: 11, Byte: 10}, 29 }, 30 }, 31 ``, 32 }, 33 { 34 `module.foo[2]`, 35 &Target{ 36 Subject: ModuleInstance{ 37 { 38 Name: "foo", 39 InstanceKey: IntKey(2), 40 }, 41 }, 42 SourceRange: tfdiags.SourceRange{ 43 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 44 End: tfdiags.SourcePos{Line: 1, Column: 14, Byte: 13}, 45 }, 46 }, 47 ``, 48 }, 49 { 50 `module.foo[2].module.bar`, 51 &Target{ 52 Subject: ModuleInstance{ 53 { 54 Name: "foo", 55 InstanceKey: IntKey(2), 56 }, 57 { 58 Name: "bar", 59 }, 60 }, 61 SourceRange: tfdiags.SourceRange{ 62 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 63 End: tfdiags.SourcePos{Line: 1, Column: 25, Byte: 24}, 64 }, 65 }, 66 ``, 67 }, 68 { 69 `aws_instance.foo`, 70 &Target{ 71 Subject: AbsResource{ 72 Resource: Resource{ 73 Mode: ManagedResourceMode, 74 Type: "aws_instance", 75 Name: "foo", 76 }, 77 Module: RootModuleInstance, 78 }, 79 SourceRange: tfdiags.SourceRange{ 80 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 81 End: tfdiags.SourcePos{Line: 1, Column: 17, Byte: 16}, 82 }, 83 }, 84 ``, 85 }, 86 { 87 `aws_instance.foo[1]`, 88 &Target{ 89 Subject: AbsResourceInstance{ 90 Resource: ResourceInstance{ 91 Resource: Resource{ 92 Mode: ManagedResourceMode, 93 Type: "aws_instance", 94 Name: "foo", 95 }, 96 Key: IntKey(1), 97 }, 98 Module: RootModuleInstance, 99 }, 100 SourceRange: tfdiags.SourceRange{ 101 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 102 End: tfdiags.SourcePos{Line: 1, Column: 20, Byte: 19}, 103 }, 104 }, 105 ``, 106 }, 107 { 108 `data.aws_instance.foo`, 109 &Target{ 110 Subject: AbsResource{ 111 Resource: Resource{ 112 Mode: DataResourceMode, 113 Type: "aws_instance", 114 Name: "foo", 115 }, 116 Module: RootModuleInstance, 117 }, 118 SourceRange: tfdiags.SourceRange{ 119 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 120 End: tfdiags.SourcePos{Line: 1, Column: 22, Byte: 21}, 121 }, 122 }, 123 ``, 124 }, 125 { 126 `data.aws_instance.foo[1]`, 127 &Target{ 128 Subject: AbsResourceInstance{ 129 Resource: ResourceInstance{ 130 Resource: Resource{ 131 Mode: DataResourceMode, 132 Type: "aws_instance", 133 Name: "foo", 134 }, 135 Key: IntKey(1), 136 }, 137 Module: RootModuleInstance, 138 }, 139 SourceRange: tfdiags.SourceRange{ 140 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 141 End: tfdiags.SourcePos{Line: 1, Column: 25, Byte: 24}, 142 }, 143 }, 144 ``, 145 }, 146 { 147 `module.foo.aws_instance.bar`, 148 &Target{ 149 Subject: AbsResource{ 150 Resource: Resource{ 151 Mode: ManagedResourceMode, 152 Type: "aws_instance", 153 Name: "bar", 154 }, 155 Module: ModuleInstance{ 156 {Name: "foo"}, 157 }, 158 }, 159 SourceRange: tfdiags.SourceRange{ 160 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 161 End: tfdiags.SourcePos{Line: 1, Column: 28, Byte: 27}, 162 }, 163 }, 164 ``, 165 }, 166 { 167 `module.foo.module.bar.aws_instance.baz`, 168 &Target{ 169 Subject: AbsResource{ 170 Resource: Resource{ 171 Mode: ManagedResourceMode, 172 Type: "aws_instance", 173 Name: "baz", 174 }, 175 Module: ModuleInstance{ 176 {Name: "foo"}, 177 {Name: "bar"}, 178 }, 179 }, 180 SourceRange: tfdiags.SourceRange{ 181 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 182 End: tfdiags.SourcePos{Line: 1, Column: 39, Byte: 38}, 183 }, 184 }, 185 ``, 186 }, 187 { 188 `module.foo.module.bar.aws_instance.baz["hello"]`, 189 &Target{ 190 Subject: AbsResourceInstance{ 191 Resource: ResourceInstance{ 192 Resource: Resource{ 193 Mode: ManagedResourceMode, 194 Type: "aws_instance", 195 Name: "baz", 196 }, 197 Key: StringKey("hello"), 198 }, 199 Module: ModuleInstance{ 200 {Name: "foo"}, 201 {Name: "bar"}, 202 }, 203 }, 204 SourceRange: tfdiags.SourceRange{ 205 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 206 End: tfdiags.SourcePos{Line: 1, Column: 48, Byte: 47}, 207 }, 208 }, 209 ``, 210 }, 211 { 212 `module.foo.data.aws_instance.bar`, 213 &Target{ 214 Subject: AbsResource{ 215 Resource: Resource{ 216 Mode: DataResourceMode, 217 Type: "aws_instance", 218 Name: "bar", 219 }, 220 Module: ModuleInstance{ 221 {Name: "foo"}, 222 }, 223 }, 224 SourceRange: tfdiags.SourceRange{ 225 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 226 End: tfdiags.SourcePos{Line: 1, Column: 33, Byte: 32}, 227 }, 228 }, 229 ``, 230 }, 231 { 232 `module.foo.module.bar.data.aws_instance.baz`, 233 &Target{ 234 Subject: AbsResource{ 235 Resource: Resource{ 236 Mode: DataResourceMode, 237 Type: "aws_instance", 238 Name: "baz", 239 }, 240 Module: ModuleInstance{ 241 {Name: "foo"}, 242 {Name: "bar"}, 243 }, 244 }, 245 SourceRange: tfdiags.SourceRange{ 246 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 247 End: tfdiags.SourcePos{Line: 1, Column: 44, Byte: 43}, 248 }, 249 }, 250 ``, 251 }, 252 { 253 `module.foo.module.bar[0].data.aws_instance.baz`, 254 &Target{ 255 Subject: AbsResource{ 256 Resource: Resource{ 257 Mode: DataResourceMode, 258 Type: "aws_instance", 259 Name: "baz", 260 }, 261 Module: ModuleInstance{ 262 {Name: "foo", InstanceKey: NoKey}, 263 {Name: "bar", InstanceKey: IntKey(0)}, 264 }, 265 }, 266 SourceRange: tfdiags.SourceRange{ 267 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 268 End: tfdiags.SourcePos{Line: 1, Column: 47, Byte: 46}, 269 }, 270 }, 271 ``, 272 }, 273 { 274 `module.foo.module.bar["a"].data.aws_instance.baz["hello"]`, 275 &Target{ 276 Subject: AbsResourceInstance{ 277 Resource: ResourceInstance{ 278 Resource: Resource{ 279 Mode: DataResourceMode, 280 Type: "aws_instance", 281 Name: "baz", 282 }, 283 Key: StringKey("hello"), 284 }, 285 Module: ModuleInstance{ 286 {Name: "foo", InstanceKey: NoKey}, 287 {Name: "bar", InstanceKey: StringKey("a")}, 288 }, 289 }, 290 SourceRange: tfdiags.SourceRange{ 291 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 292 End: tfdiags.SourcePos{Line: 1, Column: 58, Byte: 57}, 293 }, 294 }, 295 ``, 296 }, 297 { 298 `module.foo.module.bar.data.aws_instance.baz["hello"]`, 299 &Target{ 300 Subject: AbsResourceInstance{ 301 Resource: ResourceInstance{ 302 Resource: Resource{ 303 Mode: DataResourceMode, 304 Type: "aws_instance", 305 Name: "baz", 306 }, 307 Key: StringKey("hello"), 308 }, 309 Module: ModuleInstance{ 310 {Name: "foo"}, 311 {Name: "bar"}, 312 }, 313 }, 314 SourceRange: tfdiags.SourceRange{ 315 Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, 316 End: tfdiags.SourcePos{Line: 1, Column: 53, Byte: 52}, 317 }, 318 }, 319 ``, 320 }, 321 322 { 323 `aws_instance`, 324 nil, 325 `Resource specification must include a resource type and name.`, 326 }, 327 { 328 `module`, 329 nil, 330 `Prefix "module." must be followed by a module name.`, 331 }, 332 { 333 `module["baz"]`, 334 nil, 335 `Prefix "module." must be followed by a module name.`, 336 }, 337 { 338 `module.baz.bar`, 339 nil, 340 `Resource specification must include a resource type and name.`, 341 }, 342 { 343 `aws_instance.foo.bar`, 344 nil, 345 `Resource instance key must be given in square brackets.`, 346 }, 347 { 348 `aws_instance.foo[1].baz`, 349 nil, 350 `Unexpected extra operators after address.`, 351 }, 352 } 353 354 for _, test := range tests { 355 t.Run(test.Input, func(t *testing.T) { 356 traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(test.Input), "", hcl.Pos{Line: 1, Column: 1}) 357 if travDiags.HasErrors() { 358 t.Fatal(travDiags.Error()) 359 } 360 361 got, diags := ParseTarget(traversal) 362 363 switch len(diags) { 364 case 0: 365 if test.WantErr != "" { 366 t.Fatalf("succeeded; want error: %s", test.WantErr) 367 } 368 case 1: 369 if test.WantErr == "" { 370 t.Fatalf("unexpected diagnostics: %s", diags.Err()) 371 } 372 if got, want := diags[0].Description().Detail, test.WantErr; got != want { 373 t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want) 374 } 375 default: 376 t.Fatalf("too many diagnostics: %s", diags.Err()) 377 } 378 379 if diags.HasErrors() { 380 return 381 } 382 383 for _, problem := range deep.Equal(got, test.Want) { 384 t.Errorf(problem) 385 } 386 }) 387 } 388 }