# Hiera data lookup for multiple instances, with default values in hiera

Hi!

I am wondering what to be the best way organize data in a scenario where I have multiple instances of some class, for example tomcat and in this class multiple entries for, for example, connectors. This question actually consists of a number of questions about best design for my purpose. When I think what I want to achieve my ideal solution would be something like this:

In my hiera.yaml:

:hierarchy:
-   "%{::clientcert}"
-   sec_base
-   common


Approach A:

class profile::tomcat {
include ::tomcat
}


Now what I want to achieve is the possibility to have 1 instance on machineA and 4 instances on machineB. I could have:

$inst = hiera_hash(‘tomcat::instances’)$def = hiera_hash(‘tomcat::sec_baseline’)
create_resources(‘$instances’,’tomcat’,$def)


and in "%{::clientcert}".yaml:

tomcat::instances:
i01
catalina_base: “path”
i02
catalina_base: “different_path”


and in sec_base.yaml:

tomcat::sec_baseline:
catalina_base: “secret path”


Questions:

1) How can I have default parameters for each instance? For example path, http port and so on?

2) Can I use port calculation? Something like $base_port + ($offset * $instance)? How? Approach B: I could use deepmerge hierahash like so: $inst = hiera_hash(‘tomcat::instances’)

create_resources(‘$instances’,’tomcatf)  and in "%{::clientcert}".yaml:  tomcat::instances: i01 catalina_base: “path” i02 catalina_base: “different_path”  and in sec_base.yaml:  tomcat::instances: i01 catalina_base: “secure_path” i02 catalina_base: “different_secure_path”  I consider this the best option, but: Questions: 1) That would mean I lose the possibility to have different number of instances per node because if I had one instance defined in %{::clientcert}".yaml and default values for 4 instances in secbase.yaml deepmerge would alywas merg it to 4 instances, correct? Approach C: class profile::tomcat01 { include ::tomcat01 } Now what I want to achieve is the possibility to have 1 instance on machineA and 4 instances on machineB. I could have: role::machineA { include profile::tomcat01 } role::machineB{ include profile::tomcat01 … include profile::tomcat04 } profile::tomcat01( catalina_base01 = ‘path’ ){}  And in each profile::tomcatXX I would have to configure each instance individually and have set of variables for each instance independently. When I want to update my tomcat class I would have to update each profile manually. I gain “visibility/readability” and a lot of manual work. Questions: 1) Which approach should prove better in the long run? I have to maintain flexibility. I need to provide ability to have multiple instaces on different nodes, on different roles and on different environments. 2) Is there a way to set values for different instances in hiera not in a hash table? Or a better one that I was using? 3) Is there ANY resource that treats about multiple instance of whatever and how to set it up in a complete way? Modules, profiles and hiera? 4) Is there a third way? :) EDIT: alexharv074, sinned, thank you for your comments. Just to clarify though: 1) multiple instances are essetianl for me. 2) I don't have Puppet 4.0 nor plans to upgrade soon :( 3) What I am looking for are default defaults in ::params class (the puppet way ... edit retag close merge delete ## 2 Answers Sort by » oldest newest most voted Unless you know that you need support for multiple tomcat instances per node, then it's very bad practice to over-engineer a solution for the sake of forwards-compatibility. Your wording suggests that you may be doing just that, in which case the answer is (B). Regarding your specific questions - 1) How can I have default parameters for each instance? For example path, http port and so on? You can do this by either using resource defaults, or by passing a defaults hash to create_resources. Have a look here. 2) Can I use port calculation? Something like$base_port + ($offset *$instance)? How?

You can do this, but I don't recommend it. The benefit is one less parameter to configure, which doesn't really make any difference; the cost is code that makes it harder to figure out what the port number is and how it gets set. If you decide to do it anyway, your syntax looks OK.

1) That would mean I lose the possibility to have different number of instances per node because if I had one instance defined in %{::clientcert}".yaml and default values for 4 instances in secbase.yaml deepmerge would alywas merg it to 4 instances, correct?

I believe so.

1) Which approach should prove better in the long run? I have to maintain flexibility. I need to provide ability to have multiple instaces on different nodes, on different roles and on different environments.

Flexibility is just code that can be changed easily. Don't build in features just because you think you might need them one day.

2) Is there a way to set values for different instances in hiera not in a hash table? Or a better one that I was using?

I'm not understanding you.

3) Is there ANY resource that treats about multiple instance of whatever and how to set it up in a complete way? Modules, profiles and hiera?

I trust your googling is as good as mine. :)

UPDATE 1

Concerning your point (4) you should be able to specify as many defaults hashes in hiera as you like, so long as you take care of explictly merging them in your Puppet code into a single $def hash that you can then pass to create_resources's 3rd argument. UPDATE 2 I mean something like: include stdlib$instances = hiera_hash('tomcat::instances')
$sec_base = hiera_hash('tomcat::sec_base')$glob_defs = hiera_hash('tomcat::glob_defs')

$def = merge($glob_defs, $sec_base) # hash to the right 'wins' if there's conflict create_resources($instances, 'tomcat', $def)  more ## Comments Hi! I am not sure I understand your update about create_resources? Can you provide a code? The one that I showed in my example does not work. What am I doing wrong? ( 2015-07-10 08:13:58 -0600 )edit Sure, done. ( 2015-07-11 07:35:21 -0600 )edit Hi again! Thanks for that code. I didn't know I could do that... but it is not what I meant :) How do I keep def values in hiera for a couple of instances? Like in my code: tomcat::instances: i01 catalina_base: “secure_path” i02 catalina_base: “different_secure_path” ( 2015-07-13 01:31:06 -0600 )edit OK - I'm confused. In your update you wrote, "[the] create_resources third parameter would be of much use if I could pass a similar hiera_hash as the second parameter, meaning:..." And what follows looks fine to me. Can you elaborate on what's not working? ( 2015-07-14 19:44:56 -0600 )edit You could do something like this: In your "%{::clientcert}.yaml": machine1: schema: tomcat: para1: value1 para2: value2 ... instances: [inst1, inst2, inst3, inst4]  Then, in your profile: $machine1 = hiera('machine1')
$machine1['instances'].each |$foo| {
create_resources(tomcat, hiera('machine1')['schema'])
}


each is available in Puppet 4 and later.

When you have the same schema for differenct machines, you could use hiera interpolation tokens to avoid redundancy in your config.

If you want to use defaults from somewhere else, be aware that create_resources has a third parameter for that.

Warning: I am not entirely sure about the syntax in the code above, but I think it should work.

edit1: Regarding your question how to have resources affect multiple instances: You may want to have a look at virtual resources. You can define them in one file and "gather" them on all instances you wish to. I am not sure though if this is what you are looking for.

more