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  }