github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/config/raw_config_test.go (about) 1 package config 2 3 import ( 4 "encoding/gob" 5 "reflect" 6 "testing" 7 8 "github.com/hashicorp/hil/ast" 9 ) 10 11 func TestNewRawConfig(t *testing.T) { 12 raw := map[string]interface{}{ 13 "foo": "${var.bar}", 14 "bar": `${file("boom.txt")}`, 15 } 16 17 rc, err := NewRawConfig(raw) 18 if err != nil { 19 t.Fatalf("err: %s", err) 20 } 21 22 if len(rc.Interpolations) != 2 { 23 t.Fatalf("bad: %#v", rc.Interpolations) 24 } 25 if len(rc.Variables) != 1 { 26 t.Fatalf("bad: %#v", rc.Variables) 27 } 28 } 29 30 func TestRawConfig_basic(t *testing.T) { 31 raw := map[string]interface{}{ 32 "foo": "${var.bar}", 33 } 34 35 rc, err := NewRawConfig(raw) 36 if err != nil { 37 t.Fatalf("err: %s", err) 38 } 39 40 // Before interpolate, Config() should be the raw 41 if !reflect.DeepEqual(rc.Config(), raw) { 42 t.Fatalf("bad: %#v", rc.Config()) 43 } 44 45 vars := map[string]ast.Variable{ 46 "var.bar": ast.Variable{ 47 Value: "baz", 48 Type: ast.TypeString, 49 }, 50 } 51 if err := rc.Interpolate(vars); err != nil { 52 t.Fatalf("err: %s", err) 53 } 54 55 actual := rc.Config() 56 expected := map[string]interface{}{ 57 "foo": "baz", 58 } 59 60 if !reflect.DeepEqual(actual, expected) { 61 t.Fatalf("bad: %#v", actual) 62 } 63 if len(rc.UnknownKeys()) != 0 { 64 t.Fatalf("bad: %#v", rc.UnknownKeys()) 65 } 66 } 67 68 func TestRawConfig_double(t *testing.T) { 69 raw := map[string]interface{}{ 70 "foo": "${var.bar}", 71 } 72 73 rc, err := NewRawConfig(raw) 74 if err != nil { 75 t.Fatalf("err: %s", err) 76 } 77 78 vars := map[string]ast.Variable{ 79 "var.bar": ast.Variable{ 80 Value: "baz", 81 Type: ast.TypeString, 82 }, 83 } 84 if err := rc.Interpolate(vars); err != nil { 85 t.Fatalf("err: %s", err) 86 } 87 88 actual := rc.Config() 89 expected := map[string]interface{}{ 90 "foo": "baz", 91 } 92 93 if !reflect.DeepEqual(actual, expected) { 94 t.Fatalf("bad: %#v", actual) 95 } 96 97 vars = map[string]ast.Variable{ 98 "var.bar": ast.Variable{ 99 Value: "what", 100 Type: ast.TypeString, 101 }, 102 } 103 if err := rc.Interpolate(vars); err != nil { 104 t.Fatalf("err: %s", err) 105 } 106 107 actual = rc.Config() 108 expected = map[string]interface{}{ 109 "foo": "what", 110 } 111 112 if !reflect.DeepEqual(actual, expected) { 113 t.Fatalf("bad: %#v", actual) 114 } 115 } 116 117 func TestRawConfigInterpolate_escaped(t *testing.T) { 118 raw := map[string]interface{}{ 119 "foo": "bar-$${baz}", 120 } 121 122 rc, err := NewRawConfig(raw) 123 if err != nil { 124 t.Fatalf("err: %s", err) 125 } 126 127 // Before interpolate, Config() should be the raw 128 if !reflect.DeepEqual(rc.Config(), raw) { 129 t.Fatalf("bad: %#v", rc.Config()) 130 } 131 132 if err := rc.Interpolate(nil); err != nil { 133 t.Fatalf("err: %s", err) 134 } 135 136 actual := rc.Config() 137 expected := map[string]interface{}{ 138 "foo": "bar-${baz}", 139 } 140 141 if !reflect.DeepEqual(actual, expected) { 142 t.Fatalf("bad: %#v", actual) 143 } 144 if len(rc.UnknownKeys()) != 0 { 145 t.Fatalf("bad: %#v", rc.UnknownKeys()) 146 } 147 } 148 149 func TestRawConfig_merge(t *testing.T) { 150 raw1 := map[string]interface{}{ 151 "foo": "${var.foo}", 152 "bar": "${var.bar}", 153 } 154 155 rc1, err := NewRawConfig(raw1) 156 if err != nil { 157 t.Fatalf("err: %s", err) 158 } 159 160 { 161 vars := map[string]ast.Variable{ 162 "var.foo": ast.Variable{ 163 Value: "foovalue", 164 Type: ast.TypeString, 165 }, 166 "var.bar": ast.Variable{ 167 Value: "nope", 168 Type: ast.TypeString, 169 }, 170 } 171 if err := rc1.Interpolate(vars); err != nil { 172 t.Fatalf("err: %s", err) 173 } 174 } 175 176 raw2 := map[string]interface{}{ 177 "bar": "${var.bar}", 178 "baz": "${var.baz}", 179 } 180 181 rc2, err := NewRawConfig(raw2) 182 if err != nil { 183 t.Fatalf("err: %s", err) 184 } 185 186 { 187 vars := map[string]ast.Variable{ 188 "var.bar": ast.Variable{ 189 Value: "barvalue", 190 Type: ast.TypeString, 191 }, 192 "var.baz": ast.Variable{ 193 Value: UnknownVariableValue, 194 Type: ast.TypeUnknown, 195 }, 196 } 197 if err := rc2.Interpolate(vars); err != nil { 198 t.Fatalf("err: %s", err) 199 } 200 } 201 202 // Merge the two 203 rc3 := rc1.Merge(rc2) 204 205 // Raw should be merged 206 raw3 := map[string]interface{}{ 207 "foo": "${var.foo}", 208 "bar": "${var.bar}", 209 "baz": "${var.baz}", 210 } 211 if !reflect.DeepEqual(rc3.Raw, raw3) { 212 t.Fatalf("bad: %#v", rc3.Raw) 213 } 214 215 actual := rc3.Config() 216 expected := map[string]interface{}{ 217 "foo": "foovalue", 218 "bar": "barvalue", 219 "baz": UnknownVariableValue, 220 } 221 if !reflect.DeepEqual(actual, expected) { 222 t.Fatalf("bad: %#v", actual) 223 } 224 225 expectedKeys := []string{"baz"} 226 if !reflect.DeepEqual(rc3.UnknownKeys(), expectedKeys) { 227 t.Fatalf("bad: %#v", rc3.UnknownKeys()) 228 } 229 } 230 231 func TestRawConfig_syntax(t *testing.T) { 232 raw := map[string]interface{}{ 233 "foo": "${var", 234 } 235 236 if _, err := NewRawConfig(raw); err == nil { 237 t.Fatal("should error") 238 } 239 } 240 241 func TestRawConfig_unknown(t *testing.T) { 242 raw := map[string]interface{}{ 243 "foo": "${var.bar}", 244 } 245 246 rc, err := NewRawConfig(raw) 247 if err != nil { 248 t.Fatalf("err: %s", err) 249 } 250 251 vars := map[string]ast.Variable{ 252 "var.bar": ast.Variable{ 253 Value: UnknownVariableValue, 254 Type: ast.TypeUnknown, 255 }, 256 } 257 if err := rc.Interpolate(vars); err != nil { 258 t.Fatalf("err: %s", err) 259 } 260 261 actual := rc.Config() 262 expected := map[string]interface{}{"foo": UnknownVariableValue} 263 264 if !reflect.DeepEqual(actual, expected) { 265 t.Fatalf("bad: %#v", actual) 266 } 267 268 expectedKeys := []string{"foo"} 269 if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) { 270 t.Fatalf("bad: %#v", rc.UnknownKeys()) 271 } 272 } 273 274 func TestRawConfig_unknownPartial(t *testing.T) { 275 raw := map[string]interface{}{ 276 "foo": "${var.bar}/32", 277 } 278 279 rc, err := NewRawConfig(raw) 280 if err != nil { 281 t.Fatalf("err: %s", err) 282 } 283 284 vars := map[string]ast.Variable{ 285 "var.bar": ast.Variable{ 286 Value: UnknownVariableValue, 287 Type: ast.TypeUnknown, 288 }, 289 } 290 if err := rc.Interpolate(vars); err != nil { 291 t.Fatalf("err: %s", err) 292 } 293 294 actual := rc.Config() 295 expected := map[string]interface{}{"foo": UnknownVariableValue} 296 297 if !reflect.DeepEqual(actual, expected) { 298 t.Fatalf("bad: %#v", actual) 299 } 300 301 expectedKeys := []string{"foo"} 302 if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) { 303 t.Fatalf("bad: %#v", rc.UnknownKeys()) 304 } 305 } 306 307 func TestRawConfig_unknownPartialList(t *testing.T) { 308 raw := map[string]interface{}{ 309 "foo": []interface{}{ 310 "${var.bar}/32", 311 }, 312 } 313 314 rc, err := NewRawConfig(raw) 315 if err != nil { 316 t.Fatalf("err: %s", err) 317 } 318 319 vars := map[string]ast.Variable{ 320 "var.bar": ast.Variable{ 321 Value: UnknownVariableValue, 322 Type: ast.TypeUnknown, 323 }, 324 } 325 if err := rc.Interpolate(vars); err != nil { 326 t.Fatalf("err: %s", err) 327 } 328 329 actual := rc.Config() 330 expected := map[string]interface{}{"foo": []interface{}{UnknownVariableValue}} 331 332 if !reflect.DeepEqual(actual, expected) { 333 t.Fatalf("bad: %#v", actual) 334 } 335 336 expectedKeys := []string{"foo"} 337 if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) { 338 t.Fatalf("bad: %#v", rc.UnknownKeys()) 339 } 340 } 341 342 // This tests a race found where we were not maintaining the "slice index" 343 // accounting properly. The result would be that some computed keys would 344 // look like they had no slice index when they in fact do. This test is not 345 // very reliable but it did fail before the fix and passed after. 346 func TestRawConfig_sliceIndexLoss(t *testing.T) { 347 raw := map[string]interface{}{ 348 "slice": []map[string]interface{}{ 349 map[string]interface{}{ 350 "foo": []interface{}{"foo/${var.unknown}"}, 351 "bar": []interface{}{"bar"}, 352 }, 353 }, 354 } 355 356 vars := map[string]ast.Variable{ 357 "var.unknown": ast.Variable{ 358 Value: UnknownVariableValue, 359 Type: ast.TypeUnknown, 360 }, 361 "var.known": ast.Variable{ 362 Value: "123456", 363 Type: ast.TypeString, 364 }, 365 } 366 367 // We run it a lot because its fast and we try to get a race out 368 for i := 0; i < 50; i++ { 369 rc, err := NewRawConfig(raw) 370 if err != nil { 371 t.Fatalf("err: %s", err) 372 } 373 374 if err := rc.Interpolate(vars); err != nil { 375 t.Fatalf("err: %s", err) 376 } 377 378 expectedKeys := []string{"slice.0.foo"} 379 if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) { 380 t.Fatalf("bad: %#v", rc.UnknownKeys()) 381 } 382 } 383 } 384 385 func TestRawConfigCopy(t *testing.T) { 386 raw := map[string]interface{}{ 387 "foo": "${var.bar}", 388 } 389 390 rc, err := NewRawConfig(raw) 391 if err != nil { 392 t.Fatalf("err: %s", err) 393 } 394 395 rc.Key = "foo" 396 if rc.Value() != "${var.bar}" { 397 t.Fatalf("err: %#v", rc.Value()) 398 } 399 400 // Interpolate the first one 401 vars := map[string]ast.Variable{ 402 "var.bar": ast.Variable{ 403 Value: "baz", 404 Type: ast.TypeString, 405 }, 406 } 407 if err := rc.Interpolate(vars); err != nil { 408 t.Fatalf("err: %s", err) 409 } 410 411 if rc.Value() != "baz" { 412 t.Fatalf("bad: %#v", rc.Value()) 413 } 414 415 // Copy and interpolate 416 { 417 rc2 := rc.Copy() 418 if rc2.Value() != "${var.bar}" { 419 t.Fatalf("err: %#v", rc2.Value()) 420 } 421 422 vars := map[string]ast.Variable{ 423 "var.bar": ast.Variable{ 424 Value: "qux", 425 Type: ast.TypeString, 426 }, 427 } 428 if err := rc2.Interpolate(vars); err != nil { 429 t.Fatalf("err: %s", err) 430 } 431 432 if rc2.Value() != "qux" { 433 t.Fatalf("bad: %#v", rc2.Value()) 434 } 435 } 436 } 437 438 func TestRawConfigValue(t *testing.T) { 439 raw := map[string]interface{}{ 440 "foo": "${var.bar}", 441 } 442 443 rc, err := NewRawConfig(raw) 444 if err != nil { 445 t.Fatalf("err: %s", err) 446 } 447 448 rc.Key = "" 449 if rc.Value() != nil { 450 t.Fatalf("bad: %#v", rc.Value()) 451 } 452 453 rc.Key = "foo" 454 if rc.Value() != "${var.bar}" { 455 t.Fatalf("err: %#v", rc.Value()) 456 } 457 458 vars := map[string]ast.Variable{ 459 "var.bar": ast.Variable{ 460 Value: "baz", 461 Type: ast.TypeString, 462 }, 463 } 464 if err := rc.Interpolate(vars); err != nil { 465 t.Fatalf("err: %s", err) 466 } 467 468 if rc.Value() != "baz" { 469 t.Fatalf("bad: %#v", rc.Value()) 470 } 471 } 472 473 func TestRawConfig_implGob(t *testing.T) { 474 var _ gob.GobDecoder = new(RawConfig) 475 var _ gob.GobEncoder = new(RawConfig) 476 } 477 478 // verify that RawMap returns a identical copy 479 func TestNewRawConfig_rawMap(t *testing.T) { 480 raw := map[string]interface{}{ 481 "foo": "${var.bar}", 482 "bar": `${file("boom.txt")}`, 483 } 484 485 rc, err := NewRawConfig(raw) 486 if err != nil { 487 t.Fatalf("err: %s", err) 488 } 489 490 rawCopy := rc.RawMap() 491 if !reflect.DeepEqual(raw, rawCopy) { 492 t.Fatalf("bad: %#v", rawCopy) 493 } 494 495 // make sure they aren't the same map 496 raw["test"] = "value" 497 if reflect.DeepEqual(raw, rawCopy) { 498 t.Fatal("RawMap() didn't return a copy") 499 } 500 }