On 02/09/17 13:02, John Baird wrote:
Henrik,

I really appreciate your patience here, but I feel like there is something obvious that I am either not grasping or isn't spelled out in the documentation.

Let's say I make a function called `lookup_file` which will do the File.Read in whatever manner I need.  I can call that from my manifests to lookup the file, but how, then do I lookup the context from hiera? It's the combination of these two things that seems abstract to me and is preventing me from moving forward.  I understand how to do both individually, but I'm not sure how to retrieve the hiera context for the path from within this "other" function....

I can see that any file_backend function I create chomps the key on the first "." as we previously discussed, which means that I need to call a function BEFORE that in order to call my file_backend from within my file_lookup function, for instance.

How do I get the options and context to be used from the function my manifest will be using?  Let's assume in my manifest:
content => lookup_file('/tmp/somefile.txt')

does this work in my backend?

Puppet::Functions.create_function(:file_backend) do
   dispatch :file_backend do
     param 'String', :key
     param 'Hash', :options
     param 'Puppet::LookupContext', :context
   end

   def file_backend(key, options, context)
     searchroot = options['path']
     filename = "#{searchroot}/#{filename}"

You probably wanted to interpolate #{key} here, not #{filename} since it will always be nil here.

     # If file is found, return contents of file
     # If file is not found, context.not_found()
   end

   def lookup_file(key)
     options = :options
     context = :context
     file_backend(key, :options, :context)
   end
end


That looks like a decent start of that backend. You want to give it a name that is in your module's namespace.

I think that's the part I am struggling with... hiera knows about the context and options, but my manifest knows (or should know) the proper key to look up.  How do I combine them so I retrieve the contents of the file?


You (and the users of your module) interact with the backend via lookup.
The backend function should not be called directly from a manifest - that is difficult since you have to context in which to do the lookup. (There are ways, for testing purposes, or when delegating - but that is not the way it is supposed to be done normally).

Your backend is called from hiera because it is configured to be called in a hiera.yaml where you also give the path to the root of where the files are - and you get that in the options parameter (as you already have figured out).

There are some alternatives how you can support users - which I am showing below:

(I use a module name of "my" here.)

Alternative 1
---
A user needs to add escapes to all '.' in the filename manually when looking up. (Try this first to make sure your backend works).

  lookup("/tmp/foo'.'bar")

Not so great.

Alternative 2
---
A user calls a function that escapes all '.' in the filename.

  lookup(my::escape_dot("/tmp/foo.bar"))

You provide that escape function (see further down)

Alternative 3
---
Make your own lookup wrapping function - tell users to use that as a convenience.

  function my::lookup_file(String $file_name) {
    lookup(my::escape_dot($file_name))
  }

Users call that instead of lookup()

  my::lookup_file('/tmp/foo.bar')

They can also call lookup() directly if they want to use the options lookup() provides, but then they need to call the my::escape_dot() function.


my::escape_dot function
---
The my::escape_dot is something like:

Puppet::Functions.create_function(:'my::escape_dot') do
  dispatch :escape_dot do
    param 'String', :key
  end

  def escape_dot(str)
    str.split('.').join("'.'")
  end
end


With that escaping in place, your backend function will get the key with the '.' without the quotes.

There are a couple of corner cases with the quoting function if file names used as keys can contain single quotes, or if it can contain both single and double quotes. I hope you do not have to support those cases. (I suggest you simply document that it is illegal to use file names containing quotes, and possible check for that and give an error in the quoting function).

- henrik

On Sat, Sep 2, 2017 at 3:29 AM Henrik Lindberg <henrik.lindb...@puppet.com <mailto:henrik.lindb...@puppet.com>> wrote:

    On 01/09/17 01:32, John Baird wrote:
     > Henrik,
     >
     > I think the disconnect is coming from the fact that the documentation
     > only goes so far.  In that, I mean, what should my lookup be from my
     > manifest?
     >
     > Should my manifest be:
     > $somefile = lookup('/etc/example.txt')
     > and then specify the file_backend in my hiera.yaml?
     >
     > Or should my manifest be:
     > $somefile = file_backend('/etc/example.txt')
     > and then specify the file_backed in my hiera.yaml?
     >
     > If I do the former, is specifying the ":key" just implied?
     > If I do the latter, I end up in a situation where the file_backend
     > function is looking for more arguments than just the simple filename.
     >
     > I feel like that's what's not really clear, since the YAML and JSON
     > backends simply append the key to the options path without ever
     > specifying the actual key existing in the backend.  So it's a little
     > confusing how I should actually be interacting with the custom
    backend.
     >

    The big difference between the YAML and JSON backends is that they load
    files with keys in them. In your case the key is the "name" of the file!

    The JSON and YAML backends are of the data_hash kind. They are called
    once and must produce a hash of all the keys in the file pointed to by
    the path the backend is given. You do not want that since it would mean
    that you would have to slurp in all of the data files on the initial
    call. That could be a problem if you have lots of large files and they
    are not all needed for every compilation.

    Instead you need to deliver the value for a key per lookup of that key.
    The simple implementation takes the key appends it to the root path,
    reads that file and returns it as the value. If the file does not exist
    it should instead call $context.not_found().

    - henrik


     > On Monday, August 28, 2017 at 2:03:09 AM UTC-5, Henrik Lindberg
    wrote:
     >
     >     On 28/08/17 00:45, John Baird wrote:
     >      >     The backend function receives a path in the options hash -
     >     that path is
     >      >     guaranteed to exist - all non existing paths are simply
     >     skipped by
     >      >     hiera
     >      >     (see the linked docs how it works). Thus, you do not
    need to
     >     use any of
     >      >     the find file, etc. You can use relative paths in the
     >     hiera.yaml config
     >      >     and hiera will figure it out (see the docs).
     >      >
     >      >
     >      > Henrik,
     >      >
     >      > I believe I fully understand the context here, however, is the
     >     "options"
>      > hash not fully referenced within the "hiera.yaml" ? Basically,
     >     how do I
     >      > access the lookup of the key itself from within a puppet
    manifest
     >     as an
     >      > appendage of the options['path'].  I really believe that
    is the
     >     piece I
     >      > am just not able to connect.  Can you help me understand
    how to
     >     do this?
     >      >   Thanks!
     >      >
     >
     >     Not quite sure exactly where there is a piece of information
     >     missing, so
     >     pardon if I explain too much here.
     >
     >     When hiera 5 processes a lookup it will visit each entry in the
     >     hiera.yaml. Such an entry may use one out of several ways to
    specify a
     >     set of file paths to check for existence (path, paths, glob).
    If the
     >     path corresponds to something existing, a call is made to the
    function
     >     associated with that entry. It receives an options hash where
    path is
     >     set to the path that was found to be existing. This is
    repeated for all
     >     the existing paths found in that entry.
     >
     >     A user may have given additional options in the options hash.
     >
     >     If the mode of the lookup is "priority" (first found) the
    search for a
     >     value stops when a function produces a value for the key
    being searched
     >     for. If the search is a kind of "merge" then the search
    continues until
     >     all values for the key have been found.
     >
     >     You can use the fact that the hiera framework performs the
    existence
     >     check. If you do a glob to match all of the files your
    function will be
     >     called with each - then simply check if the leaf file name
    matches the
     >     key being looked up. Call "not_found" for all others, and
    read and
     >     return the content for the one that matches.
     >
     >     By doing that you get a small advantage in that you will not be
     >     incurring checks for lots of file existence for all of the
    keys that
     >     are
     >     irrelevant and never will have a matching file.
     >
     >     Does this help with what you were wondering about?
     >     - henrik
     >
     >     --
     >
     >     Visit my Blog "Puppet on the Edge"
     > http://puppet-on-the-edge.blogspot.se/
     >     <http://puppet-on-the-edge.blogspot.se/>
     >
     > --
     > You received this message because you are subscribed to the Google
     > Groups "Puppet Users" group.
     > To unsubscribe from this group and stop receiving emails from it,
    send
     > an email to puppet-users+unsubscr...@googlegroups.com
    <mailto:puppet-users%2bunsubscr...@googlegroups.com>
     > <mailto:puppet-users+unsubscr...@googlegroups.com
    <mailto:puppet-users%2bunsubscr...@googlegroups.com>>.
     > To view this discussion on the web visit
     >
    
https://groups.google.com/d/msgid/puppet-users/9f084cd5-73b7-4b17-9c81-8a386af77dc4%40googlegroups.com
     >
    
<https://groups.google.com/d/msgid/puppet-users/9f084cd5-73b7-4b17-9c81-8a386af77dc4%40googlegroups.com?utm_medium=email&utm_source=footer>.
     > For more options, visit https://groups.google.com/d/optout.


    --

    Visit my Blog "Puppet on the Edge"
    http://puppet-on-the-edge.blogspot.se/

    --
    You received this message because you are subscribed to a topic in
    the Google Groups "Puppet Users" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/puppet-users/TNDd6f8K6H8/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    puppet-users+unsubscr...@googlegroups.com
    <mailto:puppet-users%2bunsubscr...@googlegroups.com>.
    To view this discussion on the web visit
    
https://groups.google.com/d/msgid/puppet-users/oodq2v%241su%241%40blaine.gmane.org.
    For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscr...@googlegroups.com <mailto:puppet-users+unsubscr...@googlegroups.com>. To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/CACSjNA4Uk7hHP5zbODY4YT9BTboEVuu5WqKSJeAR83sO7ScD6A%40mail.gmail.com <https://groups.google.com/d/msgid/puppet-users/CACSjNA4Uk7hHP5zbODY4YT9BTboEVuu5WqKSJeAR83sO7ScD6A%40mail.gmail.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.


--

Visit my Blog "Puppet on the Edge"
http://puppet-on-the-edge.blogspot.se/

--
You received this message because you are subscribed to the Google Groups "Puppet 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-users/oogeir%24qon%241%40blaine.gmane.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to