calling functions from (ruby-)functions and puppet data types

451 views
Skip to first unread message

Peter Meier

unread,
Jul 24, 2017, 11:02:23 AM7/24/17
to puppet-dev, henrik....@puppet.com
Hi All,

I'm stumbling over two problems, while trying to port over a custom
hiera backend from hiera 3 to hiera 5.

I was able to simplify the problem I have to a simple example and I
think it shows

a) Documentation is wrong
b) You can't use Puppet Data types in ruby functions, at least not in my
example.

Essentially, the simplification of my problem all boils down to call
lookup with a certain set of parameters.

I have pushed an example repository that shows within a very compressed
version what is failing:

https://github.com/duritong/puppet_function_and_types

The first 2 ways (line 9 & 10) of calling the lookup function just don't
match a potential signature of lookup. And based on the signature errors
I get, I can only conclude that the official documentation at

https://docs.puppet.com/puppet/5.0/functions_ruby_implementation.html#calling-other-functions

"The second argument must be an array containing any arguments to the
function."

is *wrong*! As you can read out of the signature matching error message.

=> assumption a)

So let's then try without the arguments being an array:

Line 46 => Oh, looks like it matches, but can't compare Ruby Hash to
puppet Hash type. :/

Line 74 => Oh, looks like the String 'Hash' is not detected as Type, so
it indicates that this way of calling the function is right, but I am
still not able to define a ValueType.

=> assumption b)

So the only way it works: Line 89 which does not enforce any ValueType,
but everything else works.

I'm still pretty new to the type system and not yet deep into puppet 4/5
functions, but from my current perspective a) and b) are true.

best

~pete


signature.asc

Ryan Whitehurst

unread,
Jul 24, 2017, 1:45:53 PM7/24/17
to puppe...@googlegroups.com, henrik....@puppet.com
Your assumption a) seems to be correct, based on the implementation of call_function. The docs list the signature as call_function(name, args, &block) but the actual signature is call_function(name, *args, &block), so you need multiple arguments, not an array argument like the docs say. The first example, however, works either way because the include function accepts any number of arguments and then calls flatten on the resulting array before using it.

Now, the reason your call on line 74

    call_function('lookup', key, 'Hash', 'hash',{})

fails is that you have to pass in a ruby object for the type, not a string representation of the type. There's probably a better way that would generate an appropriate object based on the string, but this works for this case:

    call_function('lookup', key, Puppet::Pops::Types::PHashType::DEFAULT, 'hash',{})

That invocation gives the expected error message:

    Evaluation Error: Error while evaluating a Function Call, Found value has wrong type, expects a Hash value, got String

I've filed DOCUMENT-703 to correct the docs. https://tickets.puppetlabs.com/browse/DOCUMENT-703
 

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/9dc67243-42b3-3f9c-f869-676d15b55836%40immerda.ch.
For more options, visit https://groups.google.com/d/optout.

Peter Meier

unread,
Jul 24, 2017, 4:29:38 PM7/24/17
to puppe...@googlegroups.com, Ryan Whitehurst, henrik....@puppet.com
> Now, the reason your call on line 74
>
> call_function('lookup', key, 'Hash', 'hash',{})
>
> fails is that you have to pass in a ruby object for the type, not a
> string representation of the type. There's probably a better way that
> would generate an appropriate object based on the string, but this
> works for this case:
>
> call_function('lookup', key,
> Puppet::Pops::Types::PHashType::DEFAULT, 'hash',{})
>
> That invocation gives the expected error message:
>
> Evaluation Error: Error while evaluating a Function Call, Found
> value has wrong type, expects a Hash value, got String

Awesome, that works! :) I was navigating within the pops subsystem code
once into this direction, but it felt a bit too clumsy and I didn't
bother to try.

Thanks for the help!

I agree that there should be a better (and documented! ;) ) way that
would generate an appropriate object based on the string and if there
isn't there should probably be a user story about it.

> I've filed DOCUMENT-703 to correct the docs.
> https://tickets.puppetlabs.com/browse/DOCUMENT-703

Cool, thanks!

best

~pete

signature.asc

Henrik Lindberg

unread,
Jul 24, 2017, 6:33:00 PM7/24/17
to Peter Meier, puppe...@googlegroups.com, Ryan Whitehurst
On 24 Jul 2017, at 22:29, Peter Meier <peter...@immerda.ch> wrote:

Now, the reason your call on line 74

   call_function('lookup', key, 'Hash', 'hash',{})

fails is that you have to pass in a ruby object for the type, not a
string representation of the type. There's probably a better way that
would generate an appropriate object based on the string, but this
works for this case:

   call_function('lookup', key,
Puppet::Pops::Types::PHashType::DEFAULT, 'hash',{})

That invocation gives the expected error message:

   Evaluation Error: Error while evaluating a Function Call, Found
value has wrong type, expects a Hash value, got String

Awesome, that works! :) I was navigating within the pops subsystem code
once into this direction, but it felt a bit too clumsy and I didn't
bother to try.

Thanks for the help!

I agree that there should be a better (and documented! ;) ) way that
would generate an appropriate object based on the string and if there
isn't there should probably be a user story about it.


Puppet::Pops::Types::TypeParser#parse can be used to get a data type object given a
type expressed as in the puppet language. As an example - this:

tparser = Puppet::Pops::Types::TypeParser.singleton
t = tparser.parse(‘Array[String]’, scope)

would assign a data type of Array type accepting String values to the
variable t.

An alternative is to use the Puppet::Pops::Types::TypeFactory to create
the same Array[String] datatype:

tf = Puppet::Pops::Types::TypeFactory
t = tf.array_of(tf.string)

Hope those help in the future
Best,
- henrik
Reply all
Reply to author
Forward
0 new messages