github.com/yanndegat/hiera@v0.6.8/config/entry.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"strings"
     7  
     8  	"github.com/lyraproj/dgo/vf"
     9  
    10  	"github.com/lyraproj/dgo/dgo"
    11  	"github.com/lyraproj/dgo/util"
    12  	"github.com/yanndegat/hiera/api"
    13  )
    14  
    15  type (
    16  	entry struct {
    17  		cfg        *hieraCfg
    18  		dataDir    string
    19  		pluginDir  string
    20  		pluginFile string
    21  		options    dgo.Map
    22  		function   api.Function
    23  		name       string
    24  		locations  []api.Location
    25  	}
    26  )
    27  
    28  // FunctionKeys are the valid keys to use when defining a function in a hierarchy entry
    29  var FunctionKeys = []string{string(api.KindDataDig), string(api.KindDataHash), string(api.KindLookupKey)}
    30  
    31  // LocationKeys are the valid keys to use when defining locations in a hierarchy entry
    32  var LocationKeys = []string{
    33  	string(api.LcPath), `paths`,
    34  	string(api.LcGlob), `globs`,
    35  	string(api.LcURI), `uris`,
    36  	string(api.LcMappedPaths)}
    37  
    38  // ReservedOptionKeys are the option keys that are reserved by Hiera
    39  var ReservedOptionKeys = []string{string(api.LcPath), string(api.LcURI)}
    40  
    41  func (e *entry) Options() dgo.Map {
    42  	return e.options
    43  }
    44  
    45  func (e *entry) DataDir() string {
    46  	return e.dataDir
    47  }
    48  
    49  func (e *entry) PluginDir() string {
    50  	return e.pluginDir
    51  }
    52  
    53  func (e *entry) PluginFile() string {
    54  	return e.pluginFile
    55  }
    56  
    57  func (e *entry) Function() api.Function {
    58  	return e.function
    59  }
    60  
    61  func (e *entry) initialize(name string, entryHash dgo.Map) {
    62  	entryHash.EachEntry(func(me dgo.MapEntry) {
    63  		ks := me.Key().String()
    64  		v := me.Value()
    65  		if ks == `options` {
    66  			e.options = v.(dgo.Map)
    67  			e.options.EachKey(func(optKey dgo.Value) {
    68  				if util.ContainsString(ReservedOptionKeys, optKey.String()) {
    69  					panic(
    70  						fmt.Errorf(`option key '%s' used in hierarchy '%s' is reserved by Hiera`, optKey.String(), name))
    71  				}
    72  			})
    73  		} else if util.ContainsString(FunctionKeys, ks) {
    74  			if e.function != nil {
    75  				panic(fmt.Errorf(`only one of %s can be defined in hierarchy '%s'`, strings.Join(FunctionKeys, `, `), name))
    76  			}
    77  			e.function = &function{api.FunctionKind(ks), v.String()}
    78  		}
    79  	})
    80  }
    81  
    82  func (e *entry) Copy(cfg api.Config) api.Entry {
    83  	c := *e
    84  	c.cfg = cfg.(*hieraCfg)
    85  	return &c
    86  }
    87  
    88  func (e *entry) Name() string {
    89  	return e.name
    90  }
    91  
    92  func (e *entry) Locations() []api.Location {
    93  	return e.locations
    94  }
    95  
    96  func (e *entry) resolveFunction(ic api.Invocation, defaults api.Entry) {
    97  	if e.function == nil {
    98  		if defaults == nil {
    99  			e.function = &function{kind: api.KindDataHash, name: `yaml_data`}
   100  		} else {
   101  			e.function = defaults.Function()
   102  		}
   103  	} else if f, fc := e.function.Resolve(ic); fc {
   104  		e.function = f
   105  	}
   106  
   107  	if e.function == nil {
   108  		panic(fmt.Errorf(`one of %s must be defined in hierarchy '%s'`, strings.Join(FunctionKeys, `, `), e.name))
   109  	}
   110  }
   111  
   112  func (e *entry) resolveDataDir(ic api.Invocation, defaults api.Entry) {
   113  	e.resolveFunction(ic, defaults)
   114  	if e.dataDir == `` {
   115  		if defaults == nil {
   116  			e.dataDir = defaultDataDir()
   117  		} else {
   118  			e.dataDir = defaults.DataDir()
   119  		}
   120  	} else {
   121  		if d, dc := ic.InterpolateString(e.dataDir, false); dc {
   122  			e.dataDir = d.String()
   123  		}
   124  	}
   125  }
   126  
   127  func (e *entry) resolvePluginDir(ic api.Invocation, defaults api.Entry) {
   128  	if e.pluginDir == `` {
   129  		if defaults == nil {
   130  			e.pluginDir = defaultPluginDir()
   131  		} else {
   132  			e.pluginDir = defaults.PluginDir()
   133  		}
   134  	} else {
   135  		if d, dc := ic.InterpolateString(e.pluginDir, false); dc {
   136  			e.pluginDir = d.String()
   137  		}
   138  	}
   139  	if !filepath.IsAbs(e.pluginDir) {
   140  		e.pluginDir = filepath.Join(e.cfg.root, e.pluginDir)
   141  	}
   142  }
   143  
   144  func (e *entry) resolveOptions(ic api.Invocation, defaults api.Entry) {
   145  	if e.options == nil {
   146  		if defaults != nil {
   147  			e.options = defaults.Options()
   148  		}
   149  	} else if e.options.Len() > 0 {
   150  		e.options = ic.Interpolate(e.options, false).(dgo.Map)
   151  	}
   152  	if e.options == nil {
   153  		e.options = vf.Map()
   154  	}
   155  }
   156  
   157  func (e *entry) resolveLocations(ic api.Invocation) {
   158  	var dataRoot string
   159  	if filepath.IsAbs(e.dataDir) {
   160  		dataRoot = e.dataDir
   161  	} else {
   162  		dataRoot = filepath.Join(e.cfg.root, e.dataDir)
   163  	}
   164  	if e.locations != nil {
   165  		ne := make([]api.Location, 0, len(e.locations))
   166  		for _, l := range e.locations {
   167  			ne = append(ne, l.Resolve(ic, dataRoot)...)
   168  		}
   169  		e.locations = ne
   170  	}
   171  }
   172  
   173  func (e *entry) Resolve(ic api.Invocation, defaults api.Entry) api.Entry {
   174  	// Resolve interpolated strings and locations
   175  	ce := *e
   176  
   177  	ce.resolveFunction(ic, defaults)
   178  	ce.resolveDataDir(ic, defaults)
   179  	ce.resolvePluginDir(ic, defaults)
   180  	ce.resolveOptions(ic, defaults)
   181  	ce.resolveLocations(ic)
   182  
   183  	return &ce
   184  }