github.com/yanndegat/hiera@v0.6.8/lookup/lookup_test.go (about) 1 package main_test 2 3 import ( 4 "os" 5 "os/exec" 6 "path/filepath" 7 "runtime" 8 "sync" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "github.com/yanndegat/hiera/cli" 14 ) 15 16 func TestLookup_defaultInt(t *testing.T) { 17 result, err := cli.ExecuteLookup(`--default`, `23`, `--dialect`, `dgo`, `--type`, `int`, `foo`) 18 require.NoError(t, err) 19 require.Equal(t, "23\n", string(result)) 20 } 21 22 func TestLookup_defaultString(t *testing.T) { 23 result, err := cli.ExecuteLookup(`--default`, `23`, `--type`, `String`, `foo`) 24 require.NoError(t, err) 25 require.Equal(t, "\"23\"\n", string(result)) 26 } 27 28 func TestLookup_notFound(t *testing.T) { 29 result, err := cli.ExecuteLookup(`foo`) 30 require.NoError(t, err) 31 require.Equal(t, "", string(result)) 32 } 33 34 func TestLookup_defaultEmptyString(t *testing.T) { 35 result, err := cli.ExecuteLookup(`--default`, ``, `foo`) 36 require.NoError(t, err) 37 require.Equal(t, "\"\"\n", string(result)) 38 } 39 40 func TestLookup_defaultHash(t *testing.T) { 41 result, err := cli.ExecuteLookup(`--default`, `{ x: "a", y: 9 }`, `--dialect`, `dgo`, `--type`, `map[string](string|int)`, `foo`) 42 require.NoError(t, err) 43 require.Equal(t, "x: a\ny: 9\n", string(result)) 44 } 45 46 func TestLookup_defaultHash_json(t *testing.T) { 47 result, err := cli.ExecuteLookup(`--default`, `{ x: "a", y: 9 }`, `--dialect`, `dgo`, `--type`, `map[string](string|int)`, `--render-as`, `json`, `foo`) 48 require.NoError(t, err) 49 require.Equal(t, "{\"x\":\"a\",\"y\":9}\n", string(result)) 50 } 51 52 func TestLookup_defaultString_s(t *testing.T) { 53 result, err := cli.ExecuteLookup(`--default`, `xyz`, `--render-as`, `s`, `foo`) 54 require.NoError(t, err) 55 require.Equal(t, "xyz\n", string(result)) 56 } 57 58 func TestLookup_defaultString_binary(t *testing.T) { 59 result, err := cli.ExecuteLookup(`--default`, `YWJjMTIzIT8kKiYoKSctPUB+`, `--render-as`, `binary`, `foo`) 60 require.NoError(t, err) 61 require.Equal(t, "abc123!?$*&()'-=@~", string(result)) 62 } 63 64 func TestLookup_defaultArray_binary(t *testing.T) { 65 result, err := cli.ExecuteLookup(`--default`, `{12, 28, 37, 15}`, `--dialect`, `dgo`, `--type`, `[]int`, `--render-as`, `binary`, `foo`) 66 require.NoError(t, err) 67 require.Equal(t, []byte{12, 28, 37, 15}, result) 68 } 69 70 func TestLookup_facts(t *testing.T) { 71 inTestdata(func() { 72 result, err := cli.ExecuteLookup(`--facts`, `facts.yaml`, `interpolate_a`) 73 require.NoError(t, err) 74 require.Equal(t, "This is value of a\n", string(result)) 75 }) 76 } 77 78 func TestLookup_fact_interpolated_config(t *testing.T) { 79 inTestdata(func() { 80 result, err := cli.ExecuteLookup(`--facts`, `facts.yaml`, `interpolate_ca`) 81 require.NoError(t, err) 82 require.Equal(t, "This is value of c.a\n", string(result)) 83 }) 84 } 85 86 func TestLookup_vars_interpolated_config(t *testing.T) { 87 inTestdata(func() { 88 result, err := cli.ExecuteLookup(`--vars`, `facts.yaml`, `interpolate_ca`) 89 require.NoError(t, err) 90 require.Equal(t, "This is value of c.a\n", string(result)) 91 }) 92 } 93 94 func TestLookup_var_interpolated_config(t *testing.T) { 95 inTestdata(func() { 96 result, err := cli.ExecuteLookup(`--dialect`, `dgo`, `--var`, `c={a:"the option value"}`, `--var`, `data_file: by_fact`, `interpolate_ca`) 97 require.NoError(t, err) 98 require.Equal(t, "This is the option value\n", string(result)) 99 }) 100 } 101 102 func TestLookup_fact_directly(t *testing.T) { 103 inTestdata(func() { 104 result, err := cli.ExecuteLookup(`--facts`, `facts.yaml`, `--config`, `fact_directly_hiera.yaml`, `the_fact`) 105 require.NoError(t, err) 106 require.Equal(t, "value of the_fact\n", string(result)) 107 }) 108 } 109 110 func TestLookup_nullentry(t *testing.T) { 111 inTestdata(func() { 112 result, err := cli.ExecuteLookup(`nullentry`) 113 require.NoError(t, err) 114 require.Equal(t, "nv: null\n", string(result)) 115 }) 116 } 117 118 func TestLookup_emptyMap(t *testing.T) { 119 inTestdata(func() { 120 result, err := cli.ExecuteLookup(`--config`, `empty_map_hiera.yaml`, `--render-as`, `json`, `empty_map`) 121 require.NoError(t, err) 122 require.Equal(t, "{}\n", string(result)) 123 }) 124 } 125 126 func TestLookup_emptySubMap(t *testing.T) { 127 inTestdata(func() { 128 result, err := cli.ExecuteLookup(`--config`, `empty_map_hiera.yaml`, `--render-as`, `json`, `empty_sub_map`) 129 require.NoError(t, err) 130 require.Equal(t, "{\"x\":\"the x\",\"empty\":{}}\n", string(result)) 131 }) 132 } 133 134 func TestLookup_emptySubMapInArray(t *testing.T) { 135 inTestdata(func() { 136 result, err := cli.ExecuteLookup(`--config`, `empty_map_hiera.yaml`, `--render-as`, `json`, `empty_sub_map_in_array`) 137 require.NoError(t, err) 138 require.Equal(t, "[{}]\n", string(result)) 139 }) 140 } 141 142 func TestLookup_sensitive(t *testing.T) { 143 inTestdata(func() { 144 result, err := cli.ExecuteLookup(`sense`, `--render-as`, `s`) 145 require.NoError(t, err) 146 require.Equal(t, "sensitive [value redacted]\n", string(result)) 147 148 // Default rendering is yaml and the output is rich data. 149 result, err = cli.ExecuteLookup(`sense`) 150 require.NoError(t, err) 151 require.Equal(t, "__type: sensitive\n__value: Don't reveal this\n", string(result)) 152 }) 153 } 154 155 func TestLookup_renderJSON_NoDedup(t *testing.T) { 156 inTestdata(func() { 157 result, err := cli.ExecuteLookup(`non-existent`, `--dialect`, `dgo`, `--default`, 158 `{ x: "a string longer than 20 characters in length", y: "a string longer than 20 characters in length" }`, 159 `--render-as`, `json`) 160 161 require.NoError(t, err) 162 require.Equal(t, 163 `{"x":"a string longer than 20 characters in length","y":"a string longer than 20 characters in length"} 164 `, 165 string(result)) 166 }) 167 } 168 169 func TestLookup_renderYAML_NoDedup(t *testing.T) { 170 inTestdata(func() { 171 result, err := cli.ExecuteLookup(`non-existent`, `--dialect`, `dgo`, `--default`, 172 `{ x: "a string longer than 20 characters in length", y: "a string longer than 20 characters in length" }`, 173 `--render-as`, `yaml`) 174 175 require.NoError(t, err) 176 require.Equal(t, `x: a string longer than 20 characters in length 177 y: a string longer than 20 characters in length 178 `, 179 string(result)) 180 }) 181 } 182 183 func TestLookup_lookup(t *testing.T) { 184 inTestdata(func() { 185 result, err := cli.ExecuteLookup(`lookup_array`) 186 require.NoError(t, err) 187 require.Equal(t, "'{\"one\",\"two\",\"three\"}'\n", string(result)) 188 }) 189 } 190 191 func TestLookup_alias(t *testing.T) { 192 inTestdata(func() { 193 result, err := cli.ExecuteLookup(`alias_array`) 194 require.NoError(t, err) 195 require.Equal(t, "- one\n- two\n- three\n", string(result)) 196 }) 197 } 198 199 func TestLookup_strictAlias(t *testing.T) { 200 inTestdata(func() { 201 result, err := cli.ExecuteLookup(`strict_alias_array`) 202 require.NoError(t, err) 203 require.Equal(t, "- one\n- two\n- three\n", string(result)) 204 }) 205 } 206 207 func TestLookup_lookupNothing(t *testing.T) { 208 inTestdata(func() { 209 result, err := cli.ExecuteLookup(`lookup_nothing`) 210 require.NoError(t, err) 211 require.Equal(t, "\"\"\n", string(result)) 212 }) 213 } 214 215 func TestLookup_aliasNothing(t *testing.T) { 216 inTestdata(func() { 217 result, err := cli.ExecuteLookup(`alias_nothing`) 218 require.NoError(t, err) 219 require.Equal(t, "\"\"\n", string(result)) 220 }) 221 } 222 223 func TestLookup_strictAliasNothing(t *testing.T) { 224 inTestdata(func() { 225 result, err := cli.ExecuteLookup(`strict_alias_nothing`) 226 require.NoError(t, err) 227 require.Equal(t, ``, string(result)) 228 }) 229 } 230 231 func TestLookup_explain(t *testing.T) { 232 inTestdata(func() { 233 result, err := cli.ExecuteLookup(`--explain`, `--facts`, `facts.yaml`, `interpolate_ca`) 234 require.NoError(t, err) 235 require.Regexp(t, 236 `\ASearching for "interpolate_ca" 237 data_hash function 'yaml_data' 238 Path "[^"]*/testdata/hiera/common\.yaml" 239 Original path: "common\.yaml" 240 No such key: "interpolate_ca" 241 data_hash function 'yaml_data' 242 Path "[^"]*/testdata/hiera/named_by_fact\.yaml" 243 Original path: "named_%\{data_file\}.yaml" 244 Interpolation on "This is %\{c\.a\}" 245 Sub key: "a" 246 Found key: "a" value: "value of c.a" 247 Found key: "interpolate_ca" value: "This is value of c\.a" 248 \z`, filepath.ToSlash(string(result))) 249 }) 250 } 251 252 func TestLookup_explain_yaml(t *testing.T) { 253 inTestdata(func() { 254 result, err := cli.ExecuteLookup(`--explain`, `--facts`, `facts.yaml`, `--render-as`, `yaml`, `interpolate_ca`) 255 require.NoError(t, err) 256 require.Regexp(t, 257 `\A__type: hiera\.explainer 258 branches: 259 - __type: hiera\.explainLookup 260 branches: 261 - __type: hiera\.explainDataProvider 262 branches: 263 - __type: hiera\.explainLocation 264 event: not_found 265 key: interpolate_ca 266 location: 267 __type: hiera\.path 268 original: common\.yaml 269 resolved: .*/testdata/hiera/common\.yaml 270 exists: true 271 providerName: data_hash function 'yaml_data' 272 - __type: hiera\.explainDataProvider 273 branches: 274 - __type: hiera\.explainLocation 275 branches: 276 - __type: hiera\.explainInterpolate 277 branches: 278 - __type: hiera\.explainSubLookup 279 branches: 280 - __type: hiera\.explainKeySegment 281 event: found 282 key: a 283 value: value of c\.a 284 segment: a 285 subKey: c\.a 286 expression: This is %\{c\.a\} 287 event: found 288 key: interpolate_ca 289 value: This is value of c\.a 290 location: 291 __type: hiera\.path 292 original: named_%\{data_file\}\.yaml 293 resolved: .*/testdata/hiera/named_by_fact\.yaml 294 exists: true 295 providerName: data_hash function 'yaml_data' 296 event: result 297 key: interpolate_ca 298 value: This is value of c\.a 299 \z`, filepath.ToSlash(string(result))) 300 }) 301 } 302 303 func TestLookup_explain_options(t *testing.T) { 304 inTestdata(func() { 305 result, err := cli.ExecuteLookup(`--explain-options`, `--facts`, `facts.yaml`, `hash`) 306 require.NoError(t, err) 307 require.Regexp(t, 308 `\ASearching for "lookup_options" 309 Merge strategy "deep merge strategy" 310 data_hash function 'yaml_data' 311 Path "[^"]*/testdata/hiera/common\.yaml" 312 Original path: "common\.yaml" 313 Found key: "lookup_options" value: \{ 314 "hash": \{ 315 "merge": "deep" 316 \}, 317 "sense": \{ 318 "convert_to": "Sensitive" 319 \} 320 \} 321 data_hash function 'yaml_data' 322 Path "[^"]*/testdata/hiera/named_by_fact\.yaml" 323 Original path: "named_%\{data_file\}\.yaml" 324 No such key: "lookup_options" 325 Merged result: \{ 326 "hash": \{ 327 "merge": "deep" 328 \}, 329 "sense": \{ 330 "convert_to": "Sensitive" 331 \} 332 \} 333 \z`, filepath.ToSlash(string(result))) 334 }) 335 } 336 337 func TestLookup_explain_explain_options(t *testing.T) { 338 inTestdata(func() { 339 result, err := cli.ExecuteLookup(`--explain`, `--explain-options`, `--facts`, `facts.yaml`, `hash`) 340 require.NoError(t, err) 341 require.Regexp(t, 342 `\ASearching for "lookup_options" 343 Merge strategy "deep merge strategy" 344 data_hash function 'yaml_data' 345 Path "[^"]*/testdata/hiera/common\.yaml" 346 Original path: "common\.yaml" 347 Found key: "lookup_options" value: \{ 348 "hash": \{ 349 "merge": "deep" 350 \}, 351 "sense": \{ 352 "convert_to": "Sensitive" 353 \} 354 \} 355 data_hash function 'yaml_data' 356 Path "[^"]*/testdata/hiera/named_by_fact\.yaml" 357 Original path: "named_%\{data_file\}\.yaml" 358 No such key: "lookup_options" 359 Merged result: \{ 360 "hash": \{ 361 "merge": "deep" 362 \}, 363 "sense": \{ 364 "convert_to": "Sensitive" 365 \} 366 \} 367 Searching for "hash" 368 Using merge options from "lookup_options" hash 369 Merge strategy "deep merge strategy" 370 data_hash function 'yaml_data' 371 Path "[^"]*/testdata/hiera/common\.yaml" 372 Original path: "common\.yaml" 373 Found key: "hash" value: \{ 374 "one": 1, 375 "two": "two", 376 "three": \{ 377 "a": "A", 378 "c": "C" 379 \} 380 \} 381 data_hash function 'yaml_data' 382 Path "[^"]*/testdata/hiera/named_by_fact\.yaml" 383 Original path: "named_%\{data_file\}\.yaml" 384 Found key: "hash" value: \{ 385 "one": "overwritten one", 386 "three": \{ 387 "a": "overwritten A", 388 "b": "B", 389 "c": "overwritten C" 390 \} 391 \} 392 Merged result: \{ 393 "one": 1, 394 "two": "two", 395 "three": \{ 396 "a": "A", 397 "c": "C", 398 "b": "B" 399 \} 400 \} 401 \z`, filepath.ToSlash(string(result))) 402 }) 403 } 404 405 func TestLookupKey_plugin(t *testing.T) { 406 ensureTestPlugin(t) 407 inTestdata(func() { 408 result, err := cli.ExecuteLookup(`--config`, `lookup_key_plugin_hiera.yaml`, `a`) 409 require.NoError(t, err) 410 require.Equal(t, "option a\n", string(result)) 411 }) 412 } 413 414 func TestDataHash_plugin(t *testing.T) { 415 ensureTestPlugin(t) 416 inTestdata(func() { 417 result, err := cli.ExecuteLookup(`--config`, `data_hash_plugin_hiera.yaml`, `d`) 418 require.NoError(t, err) 419 require.Equal(t, "interpolate c is value c\n", string(result)) 420 }) 421 } 422 423 func TestLookup_issue75(t *testing.T) { 424 ensureTestPlugin(t) 425 for i := 0; i < 100; i++ { 426 inTestdata(func() { 427 result, err := cli.ExecuteLookup(`dns_resource_group_name`, `--config`, `dedup_hiera.yaml`, `--dialect`, `dgo`, 428 `--render-as`, `yaml`) 429 430 require.NoError(t, err) 431 require.Equal(t, `cbuk-shared-sharedproduction-dns-uksouth 432 `, 433 string(result)) 434 }) 435 } 436 } 437 438 func TestLookup_all_json(t *testing.T) { 439 ensureTestPlugin(t) 440 inTestdata(func() { 441 result, err := cli.ExecuteLookup(`hash`, `array`, `--render-as`, `json`, `--all`) 442 require.NoError(t, err) 443 require.Equal(t, `{"hash":{"one":1,"two":"two","three":{"a":"A","c":"C"}},"array":["one","two","three"]} 444 `, string(result)) 445 }) 446 } 447 448 func TestLookup_all_simple(t *testing.T) { 449 ensureTestPlugin(t) 450 inTestdata(func() { 451 result, err := cli.ExecuteLookup(`simple`, `--render-as`, `s`, `--all`) 452 require.NoError(t, err) 453 require.Equal(t, `{"simple":"value"} 454 `, string(result)) 455 }) 456 } 457 458 func TestLookup_all_not_there(t *testing.T) { 459 ensureTestPlugin(t) 460 inTestdata(func() { 461 result, err := cli.ExecuteLookup(`simple`, `not_there`, `--render-as`, `s`, `--all`) 462 require.NoError(t, err) 463 require.Equal(t, `{"simple":"value"} 464 `, string(result)) 465 }) 466 } 467 468 func TestLookup_all_type(t *testing.T) { 469 ensureTestPlugin(t) 470 inTestdata(func() { 471 result, err := cli.ExecuteLookup(`stringkey`, `intkey`, `literalkey`, `--all`, `--dialect`, `dgo`, `--render-as`, `s`, `--type`, `{"stringkey":string,"literalkey":string,"intkey":int}`) 472 require.NoError(t, err) 473 require.Equal(t, `{"stringkey":"stringvalue","intkey":1,"literalkey":"%{literalvalue}"} 474 `, string(result)) 475 }) 476 } 477 478 func TestLookup_all_invalid_type(t *testing.T) { 479 ensureTestPlugin(t) 480 inTestdata(func() { 481 _, err := cli.ExecuteLookup(`stringkey`, `intkey`, `--all`, `--dialect`, `dgo`, `--render-as`, `s`, `--type`, `{"stringkey":int,"intkey":int}`) 482 require.Error(t, err, `the value 'stringvalue' cannot be converted to an int`) 483 }) 484 } 485 486 func TestLookup_all_invalid_type_map(t *testing.T) { 487 ensureTestPlugin(t) 488 inTestdata(func() { 489 _, err := cli.ExecuteLookup(`stringkey`, `intkey`, `--all`, `--dialect`, `dgo`, `--render-as`, `s`, `--type`, `string`) 490 require.Error(t, err, `type must be a map`) 491 }) 492 } 493 494 /* 495 func TestDataHash_refuseToDie(t *testing.T) { 496 ensureTestPlugin(t) 497 inTestdata(func() { 498 _, err := cli.ExecuteLookup(`--config`, `refuse_to_die_plugin_hiera.yaml`, `a`) 499 if assert.Error(t, err) { 500 require.Regexp(t, `net/http: request canceled`, err.Error()) 501 } 502 }) 503 } 504 */ 505 506 func TestDataHash_panic(t *testing.T) { 507 ensureTestPlugin(t) 508 inTestdata(func() { 509 _, err := cli.ExecuteLookup(`--config`, `panic_plugin_hiera.yaml`, `a`) 510 if assert.Error(t, err) { 511 require.Regexp(t, `500 Internal Server Error: dit dit dit daah daah daah dit dit dit`, err.Error()) 512 } 513 }) 514 } 515 516 // Mimics: 517 // docker run --rm --hostname puppet -v $(pwd)/testdata/:/etc/puppetlabs/puppet/ -v $(pwd)/testdata/glob_hiera.yaml:/etc/puppetlabs/puppet/hiera.yaml --entrypoint puppet puppet/puppetserver lookup --facts /etc/puppetlabs/puppet/glob_facts.yaml a --explain 518 func TestLookupKey_globExpansionExistant(t *testing.T) { 519 inTestdata(func() { 520 result, err := cli.ExecuteLookup(`--config`, `glob_hiera.yaml`, `--facts`, `glob_facts.yaml`, `a`) 521 require.NoError(t, err) 522 require.Equal(t, "fragment a\n", string(result)) 523 }) 524 } 525 526 // Mimics: 527 // docker run --rm --hostname puppet -v $(pwd)/testdata/:/etc/puppetlabs/puppet/ -v $(pwd)/testdata/glob_hiera.yaml:/etc/puppetlabs/puppet/hiera.yaml --entrypoint puppet puppet/puppetserver lookup a --explain 528 func TestLookupKey_globExpansionNonExistant(t *testing.T) { 529 inTestdata(func() { 530 result, err := cli.ExecuteLookup(`--config`, `glob_hiera.yaml`, `a`) 531 require.NoError(t, err) 532 require.Equal(t, "common a\n", string(result)) 533 }) 534 } 535 536 var once = sync.Once{} 537 538 func ensureTestPlugin(t *testing.T) { 539 once.Do(func() { 540 t.Helper() 541 cw, err := os.Getwd() 542 if err != nil { 543 t.Fatal(err) 544 } 545 546 if err = os.Chdir(filepath.Join(`testdata`, `hieratestplugin`)); err != nil { 547 t.Fatal(err) 548 } 549 550 defer func() { 551 _ = os.Chdir(cw) 552 }() 553 554 pe := `hieratestplugin` 555 ps := pe + `.go` 556 if runtime.GOOS == `windows` { 557 pe += `.exe` 558 } 559 560 cmd := exec.Command(`go`, `build`, `-o`, filepath.Join(`..`, `plugin`, pe), ps) 561 cmd.Stderr = os.Stderr 562 cmd.Stdout = os.Stdout 563 if err = cmd.Run(); err != nil { 564 t.Fatal(err) 565 } 566 }) 567 } 568 569 func inTestdata(f func()) { 570 cw, err := os.Getwd() 571 if err == nil { 572 err = os.Chdir(`testdata`) 573 if err == nil { 574 defer func() { 575 _ = os.Chdir(cw) 576 }() 577 f() 578 } 579 } 580 if err != nil { 581 panic(err) 582 } 583 }