github.com/lyraproj/hiera@v1.0.0-rc4/examples/config_test.go (about) 1 package examples_test 2 3 import ( 4 "context" 5 "os" 6 "testing" 7 8 "github.com/lyraproj/dgo/dgo" 9 "github.com/lyraproj/dgo/vf" 10 "github.com/lyraproj/hiera/api" 11 "github.com/lyraproj/hiera/hiera" 12 "github.com/lyraproj/hiera/provider" 13 sdk "github.com/lyraproj/hierasdk/hiera" 14 ) 15 16 // sayHello is a very simple "lookup_key" function that just returns the result of concatenating 17 // the key with the string " world". 18 func sayHello(_ sdk.ProviderContext, key string) dgo.Value { 19 return vf.String(key + ` world`) 20 } 21 22 /* 23 Hiera will always use a single "lookup_key" function at the very top, henceforth referred to as the "top level 24 function". This function determines the hierarchy (or lack thereof) that Hiera uses. This file explains the three such 25 functions: the sayHello example function, the MuxLookupKey which aggregates other lookup_key functions, and the 26 ConfigLookupKey which sets up a hierarchy defined in a yaml configuration. 27 */ 28 29 // TestConfig_hardwired utilizes Hiera in the simplest way possible. No configuration file and no options. Just 30 // a function performing a lookup of a key. In other words, this single function is the entire hierarchy. 31 func TestConfig_hardwired(t *testing.T) { 32 // Use the hiera.DoWithParent to initialize a Hiera Session with the sayHello as the top-level function and 33 // perform a lookup. 34 // 35 // The DoWithParent is meant to be called once and the created context can then be used for any number of lookups that 36 // uses the same configuration. The session's life-cycle can be compared to the compiler's life-cycle in puppet. 37 hiera.DoWithParent(context.Background(), sayHello, nil, func(hs api.Session) { 38 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 39 if result == nil || `hello world` != result.String() { 40 t.Fatalf("unexpected result %v", result) 41 } 42 }) 43 } 44 45 // TestHelloWorld_semiHardWired uses the "lookup_key" function MuxLookupKey. This function use the configuration 46 // option LookupKeyFunctions where it expects to find a slice of "lookup_key" functions to use. Those functions form 47 // top level hierarchy that is configurable from code. Very useful if you for instance want to introduce different 48 // lookup layers such as "global", "environment", and "module" or in other ways build a complex lookup hierarchy that 49 // service that goes beyond what can be defined in the yaml configuration. 50 func TestConfig_semiHardWired(t *testing.T) { 51 // Create options valid for this Hiera session. 52 // The LookupProvidersKey stores a go slice of Hiera "lookup_key" functions that serve as the top level functions. 53 configOptions := vf.Map(provider.LookupKeyFunctions, []sdk.LookupKey{sayHello}) 54 55 // Initialize a Hiera session with the MuxLookupKey as the top-level function and perform a lookup and 56 // the created configOptions. 57 hiera.DoWithParent(context.Background(), provider.MuxLookupKey, configOptions, func(hs api.Session) { 58 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 59 if result == nil || `hello world` != result.String() { 60 t.Fatalf("unexpected result %v", result) 61 } 62 }) 63 } 64 65 /* 66 The remaining tests in this file use the ConfigLookupKey provider. This provider will consult the configuration 67 options HieraRoot, HieraConfigFileName, and HieraConfig to determine the path of the configuration file. Use of 68 HieraConfig is mutually exclusive with HieraRoot and HieraConfigFileName. 69 70 HieraRoot will default to the current working directory. 71 72 HieraConfigFileName will default to "hiera.yaml". 73 74 If the HieraRoot or HieraConfig are relative paths, they will be considered relative to the current directory. 75 76 The HieraConfigFileName must be relative to the HieraRoot. 77 */ 78 79 // TestHelloWorld_yamlConfig uses the "lookup_key" function ConfigLookupKey and HieraRoot. The ConfigLookupKey is 80 // the most commonly used top-level function in Hiera. It finds a yaml configuration on disk and then configures 81 // everything according to the hierarchy specified in that file. 82 func TestHelloWorld_yamlConfig(t *testing.T) { 83 configOptions := vf.Map(api.HieraRoot, `testdata`) 84 85 // Initialize a Hiera session with the ConfigLookupKey as the top-level function configured using the configOptions. 86 hiera.DoWithParent(context.Background(), provider.ConfigLookupKey, configOptions, func(hs api.Session) { 87 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 88 if result == nil || `yaml data says hello` != result.String() { 89 t.Fatalf("unexpected result %v", result) 90 } 91 }) 92 } 93 94 // TestHelloWorld_explicitYamlConfig is similar to TestHelloWorld_yamlConfig but uses HieraConfig 95 // option to explicitly define the file to use. 96 func TestHelloWorld_explicitYamlConfig(t *testing.T) { 97 configOptions := vf.Map(api.HieraConfig, `testdata/hiera.yaml`) 98 99 // Initialize a Hiera session with the ConfigLookupKey as the top-level function configured using the configOptions. 100 hiera.DoWithParent(context.Background(), provider.ConfigLookupKey, configOptions, func(hs api.Session) { 101 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 102 if result == nil || `yaml data says hello` != result.String() { 103 t.Fatalf("unexpected result %v", result) 104 } 105 }) 106 } 107 108 // TestHelloWorld_explicitYamlConfigEnvironment is similar to TestHelloWorld_yamlConfig but uses HIERA_CONFIGFILE 109 // environment variable to explicitly define the file to use. 110 func TestHelloWorld_explicitYamlConfigEnvironment(t *testing.T) { 111 configOptions := vf.Map(api.HieraRoot, `testdata`) 112 _ = os.Setenv("HIERA_CONFIGFILE", "hiera_env.yaml") 113 114 // Initialize a Hiera session with the ConfigLookupKey as the top-level function configured using the configOptions. 115 hiera.DoWithParent(context.Background(), provider.ConfigLookupKey, configOptions, func(hs api.Session) { 116 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 117 if result == nil || `yaml data says hello` != result.String() { 118 t.Fatalf("unexpected result %v", result) 119 } 120 }) 121 } 122 123 // TestHelloWorld_explicitYamlConfigFile is similar to TestHelloWorld_yamlConfig but uses a combination of 124 // HieraRoot and HieraConfigFileName option to find the yaml configuration file. 125 func TestHelloWorld_explicitYamlConfigFile(t *testing.T) { 126 configOptions := vf.Map( 127 api.HieraRoot, `testdata`, 128 api.HieraConfigFileName, `special.yaml`) 129 130 // Initialize a Hiera session with the ConfigLookupKey as the top-level function configured using the configOptions. 131 hiera.DoWithParent(context.Background(), provider.ConfigLookupKey, configOptions, func(hs api.Session) { 132 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 133 if result == nil || `yaml special data says hello` != result.String() { 134 t.Fatalf("unexpected result %v", result) 135 } 136 }) 137 } 138 139 // TestHelloWorld_yamlAndSemiHardWired uses the MuxLookupKey to inject two lookup_key functions. The ConfigLookupKey 140 // that consults the yaml config and the sayHello. 141 func TestHelloWorld_yamlAndSemiHardWired(t *testing.T) { 142 configOptions := vf.Map( 143 provider.LookupKeyFunctions, []sdk.LookupKey{provider.ConfigLookupKey, sayHello}, 144 api.HieraRoot, `testdata`) 145 146 // Initialize a Hiera session with the MuxLookupKey as the top-level function configured using the configOptions. 147 hiera.DoWithParent(context.Background(), provider.MuxLookupKey, configOptions, func(hs api.Session) { 148 // A lookup of just "hello" should hit the first provider, the ConfigLookupKey. 149 result := hiera.Lookup(hs.Invocation(nil, nil), `hello`, nil, nil) 150 if result == nil || `yaml data says hello` != result.String() { 151 t.Fatalf("unexpected result %v", result) 152 } 153 154 // A lookup of "howdy" is not found using the yaml configuration, so it hits the second provider, the sayHello. 155 result = hiera.Lookup(hs.Invocation(nil, nil), `howdy`, nil, nil) 156 if result == nil || `howdy world` != result.String() { 157 t.Fatalf("unexpected result %v", result) 158 } 159 }) 160 }