How to access a value in an hiera hash directly with puppet lookup? - puppet

Let's say there is an hiera hash:
foo::bar:
key1: 'value1'
key2: 'value2'
Is there any possibility to lookup the value of key1 directly with the lookup function?
I thought of something like:
class myclass (
String $value1 = lookup('foo::bar::key1'),
) {
...
}
The only way I could solve this, is to lookup the Hash and acces the value later with hash['key1'], but maybe there is a more clean way to do this.

Unfortunately, there isn't a way to do this in Puppet using just lookup.
Fundamentally, lookup works by looking up Hiera keys, which are unrelated to hash keys. A Hiera key of the form foo::bar::baz is effectively a single unstructured string - it doesn't imply that there are hashes called foo or foo::bar. The :: is just part of the key string - it isn't syntactic sugar for a hash lookup, as is, for example, . in JavaScript.
lookup is documented at
https://puppet.com/docs/puppet/latest/hiera_automatic.html

This is now possible in puppet (v6 and later)! You use dot notation
lookup('foo::bar.key1')
See the puppet documentation here: https://puppet.com/docs/puppet/7/hiera_automatic.html#access_hash_array-elements_keysubkey_notation

Related

Replacing a static Enum with a HashMap or similar

I have a simple Enum used to map to hardcoded strings:
Think:
enum SomeThing {
A, B, C
}
These values are shown in a UI as RadioButtons so the user can pick one and these options are mapped to a string (the name of a file I don't control).
The way this is done at runtime time is (pseudo-code):
let xxx: HashMap::from([
(
SomeThing::A.to_string(),
"value_for_a".to_string(),
),
(
SomeThing::B.to_string(),
"value_for_b".to_string(),
),
etc...
This is done at runtime and later used to retrieve the value for the chosen option. The fact that it's an Enum has the type safety in mind. But...
I'd like to change this code to make it user-configurable, and allow the user to specify those values themselves; since it's a runtime-constructed HashMap, I could imagine a config file (of any format like YAML) having:
---
xxx:
A: value_for_a
B: value_for_b
C: value_for_c
And parsed into "the same" HashMap (without the benefits of the Enum type safety).
The questions are:
I suppose creating an Enum at runtime would not be possible right? I'd imagine the user could create a new D key/value and or remove an existing one.
What would be another way to do this instead? Keep/Use a HashMap of some sort to store the Key (A,B,C) and their values after they were parsed?
(worth mentioning: the Enum is convenient because it's used by structopt for a command line parameter via the provided arg_enum! macro, so you can specify the posible_values as &YourEnum::variants() but this is less important to keep)
Is there a "better" way to do this that you can think of?

Is use of enums justified in this case?

So I used to maintain configurations as dicts in the past and then stumbled over enums in python.
The following is what I used to do before:
CONFIG = {
"field1": {"field11": "value11", ....},
"field2": {"field12": "value22", .....},
}
This would be a global and would contain some configuration that my application would use.
I then converted the same using enums are follows:
from enum import Enum, unique
#unique
class Config(Enum):
field1 = {"field11": "value11", .....}
field2 = {"field22": "value22", .....}
The benefit of using enums was quite hazy at first but when I dug deep, I found out enums are immutable, one can enforce uniqueness and it offers a cleaner way to iterate across its members.
I checked if this was used in any of the python third party or standard libraries. I found out that majority of them were using a class as follows:
class Config:
field1 = {"field11": "value11", .....}
field2 = {"field22": "value22", .....}
So my question is, is enums a good choice to hold configs which shouldn't be accidentally changed or its just overkill and one can get away with using a class instead?
Would like to know which one is considered as the best practise.
The main advantage of using enum in your question is that it allows the writing of symbolic constants in the code, whereas using dictionary you'd have have to check the dictionary for the key, e.g:
Config.field1
versus
Config["field1"]
So the difference would be advantage in syntax, but also that enum is inherently immutable unlike dictionary, and also that enum can't be extended unlike class.

Memoizing traversed fs paths with Node.js

I have a tool that is doing concurrent searches through a filesystem for certain files. As the tool searches through the fs, it may find that it needs to search in directories not originally included in the search.
What I should do is memoize each directory that has already started to be searched.
I can't think of a better way to memoize file paths except to store them in a hash like this:
interface IMemoizationMap {
[key: string]: boolean
}
so that might look like:
const hash = {
'/Users/you/projects/x': true,
'/Users/you/projects/x/lib': true,
'/Users/you/projects/x/lib': true,
...
...
'/Users/you/some-stuff/z': true
};
Then I do a quick lookup to see if I need to search a certain directory. What feels awkward about this solution is that the values in the hash could pretty much be anything - true, false, undefined.
Is this the best way to memoize traversed filepaths?
As an aside, is the performance of
key in hash
the same as
hash[key]
?
If that is the case, then there would be some worth to data stored as the value:
When a directory starts being searched I could make the value false, and then when the directory finishes searching I could flip the value to true. Then the value at least means something.
Go with Map:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
The Map object holds key-value pairs. Any value (both objects and
primitive values) may be used as either a key or a value.
Or Set:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Set
The Set object lets you store unique values of any type, whether
primitive values or object references.
I would choose Set, but i'm unaware of performance comparisons between both when testing if the value exists already on the collection.

Parameter mapping with Hiera

Is it possible to map hiera parameter to another one?
For example, if in hiera there is already a parameter "person::shoe::size" , and puppet module "other_module" needs to lookup parameter like this: hiera(person_shoe_size).
Is it possible to tell hiera that parameter "person_shoe_size" is the same thing as "person::shoe::size", and that hiera(person_shoe_size) should actually be mapped to hiera(person::shoe::size)?
Yes, you can do a hiera lookup inside of your value.
person::shoe::size: "7"
person_shoe_size: "%{hiera('person::shoe::size')}"
Looking up either would return 7. You can also do something like this:
hostname: "cool-hostname"
module::fully_qualified_name: "%{hiera('hostname')}.domain.tld"
Here, the fully_qualified_name parameter will have a value of cool-hostname.domain-tld.

How to access a Map using playframework template system (groovy)

I've been using the--quite excellent--playframework and have had trouble finding documentation/examples on how to access a Map data structure from a view, using play's template engine.
To be even more specific, I wish to access the Map as I iterate over a List of objects, e.g.,
#{list items:itemList, as:'item'}
// access the map value using the ${item?.id} as the key
#{/list}
Thank's for looking.
This is a generic solution to iterate on Map in using Play! Framework:
in the controller :
render(map);
in the template:
#{list items:map.keySet(), as:'key'}
${map.get(key)}
#{/list}
The fact that you want to rely on a side List to iterate on your Map suggest me that you are searching a predictible way for your iteration process.
In that case, just remember that iteration will be unpredictable if you don't use an ordered/sorted Map implementation.
HashMap gives you an unsorted, unordered Map
LinkedHashMap maintains insertion order
TreeMap is the only JDK implementation of a sorted Map. By default it allows you to iterate following the natural order of the elements. You can also specify a custom sort order and implements the Comparable interface. This will lead you to override the compareTo() method.
Assuming you do in the Controller:
render(map, itemList); //map is a Map
This should work:
#{list items:itemList, as:'item'}
// access the map value using the ${item?.id} as the key
${map.get(item.?id)}
#{/list}
I don't know anything about the play framework, but this would work in a GSP
#{list items:itemList, as:'item'}
${map[item?.id]}
#{/list}
I'm doing things like that on a map:
*{ Map<User, Integer> shareHolders = ... }*
#{list shareHolders.sort{it.value}.collect {k,v -> k}.reverse(), as:'holder'}
<tr>
<td>${holder.name}</td>
<td>${shareHolders[holder]}</td>
</tr>
#{/list}

Resources