Reputation: 65
I have this in a yaml hiera file.
reg_connection:
toronto:
- host: apple.net
- port: 701
- user: george
- ssl: true
- allowed: banana,orange
texas:
- host: pink.net
- port: 702
- user: joel
- ssl: false
- allowed: blue,gree,red
I want to access the values of host, port, user, ssl and allowed for toronto and texas.
I have this in my manifest:
$reg_connection= hiera_hash('reg_connection')
I have this in my template:
<% reg_connection.keys().sort.each do |location| -%>
<%= location %>host=<%= location[host] %>
<%= location %>port=<%= location[port] %>
<%= location %>username=<%= location[user] %>
<%= location %>ssl.enable=<%= location[ssl] %>
<%= location %>allowed.list=<%= location[allowed] %>
<% end -%>
I want this to output two blocks of configuration in my template: one for toronto and one for texas.
My puppet output shows that it doesn't have a value for host. How can i access that value?
Upvotes: 2
Views: 4333
Reputation: 106027
You have a number of problems. The first is that in this code:
<%= location[host] %>
...host
is (correctly) interpreted as a local variable or method name. There's no variable or method named host
, hence the error.
You want to access the value with the key named "host"
, which is a string, so you must use that string.
<%= location["host"] %>
The second problem is in your YAML file.
reg_connection:
toronto:
- host: apple.net
- port: 701
- user: george
- ssl: true
- allowed: banana,orange
texas:
# ...
Here your have a mapping (which is like—and is parsed into—a Ruby Hash) with a single key, reg_connection
. The value associated with that key is itself a mapping with two keys, toronto
and texas
. So far so good. But the value associated with toronto
is a sequence (read: array), not a mapping, because each line starts with -
. The mapping has five items, each of which has a single key and value. Another way to represent the same data structure is this, which may help to illustrate the problem;
{ reg_connection:
{ toronto:
[ { host: apple.net },
{ port: 701 },
{ user: george },
# ...
],
texas:
# ...
}
}
What you want, I suspect, is for that innermost data structure to be a mapping, not a sequence:
reg_connection:
toronto:
host: apple.net
port: 701
user: george
ssl: true
allowed: banana,orange
texas:
# ...
The third problem is with the way you're trying to iterate over the resulting hashes:
<% reg_connection.keys().sort.each do |location| -%>
<%= location %>host=<%= location["host"] %>
<%= location %>port=<%= location["port"] %>
...
You've called reg_connection.keys.sort.each
(note: in idiomatic Ruby, parentheses are omitted for empty argument lists), which means you're not iterating over the locations, you're iterating over the keys of the reg_connection
hash. In other words, you're iterating over the array ["toronto", "texas"]
, so the subsequent line is equivalent to"toronto"["host"]
, which isn't going to work.
You could replace location["host"]
with reg_connection[location]["host"]
, but that's overkill. Just do this:
<% reg_connection.sort.each do |location, values| -%>
<%= location %>host=<%= values["host"] %>
<%= location %>port=<%= values["port"] %>
...
There's no need to get reg_connection
's keys before calling sort
—you can just call it directly on the hash. This will, in effect, convert the hash to an array of key-value pairs (two-element arrays), which Ruby has no trouble sorting. Then when we call each
two values are passed to the block—location
(they key, e.g. "toronto"
) and values
the hash with "host"
, "port"
, etc. keys.
Upvotes: 9