creating hashes from other hashes

170 views
Skip to first unread message

Tim Mooney

unread,
Nov 6, 2014, 5:04:00 PM11/6/14
to puppet...@googlegroups.com

All-

We're using puppet (opensource) 3.4.2 master and clients. We've been
using puppet a few years, including create_resources, but this is my
first foray into creating complicated nested hashes.

I've boiled the problem I'm running into down to this example:

$ cat /tmp/foo.pp
class foo {
foo::bar { 'somevalue':
stuff => {
'one' => 'doesnt_matter',
'two' => 'doesnt_matter',
}
}
}

define foo::bar (
$stuff = {},
) {

#
# not valid: fails with a parser validation error on the key $name:
#
# Error: Could not parse for environment production: Syntax error at
# 'name';
# expected '}' at /tmp/foo.pp:21
#
$new_hash = {
$name => $stuff,
}

#
# this works, using a constant key
#
$new_hash = {
'a_constant' => $stuff,
}
}


This comes from a larger, more complicated example, but what I'm trying to
do is

- take a hash ($stuff) that has all the parameters I need
- create a new hash with a single key that's the $name/$title for the define,
and a value that contains the hash $stuff that I was passed.

As you might guess, this is to make $new_hash suitable for passing
to create_resources.

Is there some other way to create a new hash, give it a single top-level
key that is a variable, and assign a separate (passed-in as a parameter)
hash as the value for that key? I would be fine with using stdlib::merge,
but I don't see any obvious way to accomplish this task with stdlib::merge
either.

Thanks,

Tim
--
Tim Mooney Tim.M...@ndsu.edu
Enterprise Computing & Infrastructure 701-231-1076 (Voice)
Room 242-J6, Quentin Burdick Building 701-231-8541 (Fax)
North Dakota State University, Fargo, ND 58105-5164

Luke Bigum

unread,
Nov 7, 2014, 4:03:53 AM11/7/14
to puppet...@googlegroups.com
Huh, at first glance that to me looks like a parser bug. Now that I think more on it I seem to recall this coming up before. The $name of a Defined Type is not of type String, and Puppet Hash keys are always strings, according to the docs:


This code works, explicitly enclosing $name in a string:



define foo::bar (
   $stuff = {},
) {
   $new_hash = {"$name" => $stuff}
}

class foo {
   foo::bar { 'somevalue':
     stuff => {
       'one' => 'doesnt_matter',
       'two' => 'doesnt_matter',
     }
   }
}

include foo

Tim Mooney

unread,
Nov 7, 2014, 5:43:14 PM11/7/14
to puppet...@googlegroups.com
In regard to: [Puppet Users] Re: creating hashes from other hashes, Luke...:

> Huh, at first glance that to me looks like a parser bug.

That's what I was thinking too.

> Now that I think
> more on it I seem to recall this coming up before. The $name of a Defined
> Type is not of type String, and Puppet Hash keys are always strings,
> according to the docs:
>
> https://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#hashes
>
> This code works, explicitly enclosing $name in a string:

Ok, thanks. Unfortunately, we have puppet-lint hooked into our pre-commit
hook, and puppet-lint objects to a variable that is enclosed in double
quotes for no reason:

WARNING: string containing only a variable on line 39
WARNING: variable not enclosed in {} on line 39

I even tried doing this, to get around puppet-lint:

$my_key = strip(" ${name } ")
$new_pool = {
$my_key => $fpm_pool,
}

Still no joy, as now the parser objects to $my_key. This really does
seem like a bug in the parser.

It looks like I'm going to have to temporarily disable our pre-commit
hook, and check in the code using "$name".

Thanks again Luke, your insight on this is much appreciated!

Tim
>> <javascript:>

Denmat

unread,
Nov 7, 2014, 8:25:26 PM11/7/14
to puppet...@googlegroups.com
You don't need to disable lint entirely, you could just disable that check condition.

Den
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/alpine.SOC.2.11.1411071622310.23044%40dogbert.cc.ndsu.NoDak.edu.
For more options, visit https://groups.google.com/d/optout.

Henrik Lindberg

unread,
Nov 7, 2014, 9:42:41 PM11/7/14
to puppet...@googlegroups.com
On 2014-07-11 23:43, Tim Mooney wrote:
> In regard to: [Puppet Users] Re: creating hashes from other hashes,
> Luke...:
>
>> Huh, at first glance that to me looks like a parser bug.
>
Not so much a bug as an unessesary constraint.
This is changed in Puppet 4.0 (and when using --parser future in late 3x
releases).

i.e. this then works:
apply --parser future -e '$x = hello notice({$x => world})'
Notice: Scope(Class[main]): {hello => world}


> That's what I was thinking too.
>
>> Now that I think
>> more on it I seem to recall this coming up before. The $name of a Defined
>> Type is not of type String, and Puppet Hash keys are always strings,
>> according to the docs:
>>
>> https://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#hashes
>>
>>
In 3x, the keys must be strings, but the $name is a string. What is not
allowed is to have hash keys that are expressions (such as a variable
expression).

>> This code works, explicitly enclosing $name in a string:
>
> Ok, thanks. Unfortunately, we have puppet-lint hooked into our pre-commit
> hook, and puppet-lint objects to a variable that is enclosed in double
> quotes for no reason:
>
> WARNING: string containing only a variable on line 39
> WARNING: variable not enclosed in {} on line 39
>
Lint is simply complaining too much. There are several reasons for
interpolating a single variable either as "$x", or "${x}" - one such
reason is the constraint on hash keys, another is to force numeric to
string conversion - say $x = 2 + 3 which makes $x not be a string but an
Integer, some functions / uses does not do well when they receive an
Integer instead of a String, and it must be transformed to a string,
either via interpolation, or by calling the printf function.

So, while you in general do not have to do single variable
interpolation, link is wrong in complaining about it everywhere.
You could perhaps trick it by doing "${"$x"}" which is an interpolation
of an interpolation :-)

Yet another option is to call the printf function in the interpolation
expression.

Hope that helps explain why it does not work and how you can work around
it until Puppet 4.0.0 comes out.

Regards
- henrik



--

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

Tim Mooney

unread,
Nov 13, 2014, 12:17:48 PM11/13/14
to puppet...@googlegroups.com
In regard to: Re: [Puppet Users] Re: creating hashes from other hashes,...:

> On 2014-07-11 23:43, Tim Mooney wrote:
>> In regard to: [Puppet Users] Re: creating hashes from other hashes,
>> Luke...:
>>
>>> Huh, at first glance that to me looks like a parser bug.
>>
> Not so much a bug as an unessesary constraint.
> This is changed in Puppet 4.0 (and when using --parser future in late 3x
> releases).
>
> i.e. this then works:
> apply --parser future -e '$x = hello notice({$x => world})'
> Notice: Scope(Class[main]): {hello => world}

>> WARNING: string containing only a variable on line 39
>> WARNING: variable not enclosed in {} on line 39
>>
> Lint is simply complaining too much. There are several reasons for
> interpolating a single variable either as "$x", or "${x}" - one such reason is
> the constraint on hash keys, another is to force numeric to string conversion
> - say $x = 2 + 3 which makes $x not be a string but an Integer, some functions
> / uses does not do well when they receive an Integer instead of a String, and
> it must be transformed to a string, either via interpolation, or by calling
> the printf function.
>
> So, while you in general do not have to do single variable interpolation, link
> is wrong in complaining about it everywhere.
> You could perhaps trick it by doing "${"$x"}" which is an interpolation of an
> interpolation :-)
>
> Yet another option is to call the printf function in the interpolation
> expression.
>
> Hope that helps explain why it does not work and how you can work around it
> until Puppet 4.0.0 comes out.

Thanks Henrik! We're probably still a few weeks from upgrading to 3.7.x,
but when we do, getting our code ready for the future parser is also on
the list of things to do.

I had been planning on just temporarily disabling our entire pre-commit
hook, but since I've needed to use this in a couple of defines now, I did
end up going the route that Denmat suggested in a separate email, and just
used --no-only_variable_string-check with the other lint flags we're
passing to puppet-lint.

I appreciate your response and insight regarding this!

Tim
--
Tim Mooney Tim.M...@ndsu.edu
Reply all
Reply to author
Forward
0 new messages