Iterate a puppet resource collector - resources

I am trying to develop a puppet class with a defined resource which creates the configuration for a website.
One of the things that the defined resource has to do is assign the IP address of the website to a dummy interface. Due to constraints of the project this is done with NetworkManager.
So I have to generate a file like
[connection]
id=dummydsr
uuid=50819d31-8967-4321-aa34-383f4a658789
type=dummy
interface-name=dummydsr
permissions=
[ipv4]
method=manual
#IP Addresses come here
ipaddress1=1.2.3.4/32
ipaddress2=5.6.7.8/32
ipaddress3=8.7.6.5/32
[ipv6]
method=ignore
There is to be a line ipaddressX=... for every instance of the defined resource.
My problem is how do I track the number of times the defined resource has been instantiated so I can somehow increment a counter and generate the ipaddress lines.
Or for each instantiated defined resource, append the IP address to an array which I can later use to build the file

If I understand you, and I'm not certain that I do, but I think you would want to do something like this:
define mytype(
Integer $count,
...
) {
file { 'some_network_manager_file':
content => template(...)
}
}
And then you would have a loop:
$mystuff.each |$count, $data| {
mytype { ...:
count => $count,
...
}
}
Key insight here may be that the each function has some magic in it that allows you to get the index if you need it, see also this answer.
Now I think that's how it will work, without me spending time researching NetworkManager. If you provide more of your code, I may be able to update this to be more helpful.

This is less than ideal since I would prefer to have it inside the defined resource, but since I instantiate the defined resource with the data from a hash I use said hash to iterate that part.
class xxx_corp_webserver (
Hash $websites ={}
){
create_resources('xxx_corp_webserver::website', $websites)
# This would be nicer inside the defined class, but I did not find any other way
# Build and array with the IP addresses which are for DSR
$ipaddresses = $websites.map | $r | {
if $r[1]['enabledsr'] {
$r[1]['ipaddress']
}
}
# For each DSR address add the line
$ipaddresses.each | Integer $index , String $ipaddress | {
$num = $index+1
file_line{"dummydsr-ipaddress${num}":
ensure => present,
path => '/etc/NetworkManager/system-connections/dummydsr',
line => "address${num} = ${ipaddress}/32",
match => "^address.* = ${ipaddress}/32",
after => '# IP Addresses come here',
notify => Service['NetworkManager'],
require => File['/etc/NetworkManager/system-connections/dummydsr'],
}
}
}

Related

How to read keys into array?

I am trying to read keys from a hiera json file into an array.
The json is as follows:
{
"network::interfaces": {
"eth0": {
"ip": "10.111.22.10"
},
"eth1": {
"ip": "10.111.22.11"
},
"eth2": {
"ip": "10.111.22.12"
}
}
}
In my Puppet code, I am doing this:
$network_interfaces = hiera_array('network::interfaces')
notice($network_interfaces)
Which results in the following:
Notice: Scope(Class[Role::Vagrant]): {eth0 => {ip => 10.111.22.10}, eth2 => {ip => 10.111.22.11}, eth3 => {ip => 10.111.22.12}}
But what I want are just the interfaces: [eth0, eth1, eth2]
Can someone let me know how to do this?
The difference between hiera_array() and plain hiera() has to do with what happens when the requested key (network::interfaces in your case) is present at multiple hierarchy levels. It has very little to do with what form you want the data in, and nothing to do with selecting bits and pieces of data structures. hiera_array() requests an "array-merge" lookup. The more modern lookup() function refers to this as the "unique" merge strategy.
It seems unlikely that an array-merge lookup is in fact what you want. In that case, the easiest thing to do is read the whole hash and extract the keys:
$network_interfaces = keys(hiera('network::interfaces'))
In Puppet 4 you'll need to use the keys() function provided by the puppetlabs/stdlib module. From Puppet 5 on, that function appears in core Puppet.

manage hosts file on Windows using Puppet

I'm trying to manage my hosts file on a Windows machine using Puppet and Hiera. My problem is that I have never really used Hiera and I'm struggling with parsing the data content into a proper format.
The relevant section in hieradata/hiera.yaml looks like this:
myhosts : [
'host1 1.2.3.4',
'host2 2.3.4.5',
'host3 3.4.5.6']
I have code that uses a host module, but it also depends on a class that I don't have, so naturally it doesn't work.
class hosts::module (
$myhosts = hiera('myhosts'),
)
{
define update_hosts {
$value = split($name,' ')
host {
"${value[0]}" : ip => "${value[1]}",
}
}
update_hosts { $myhosts :; }
}
I have tried using the file resource instead of the host resource, and also tried doing it without any class, but for some reason I am getting this error
Error: Could not retrieve catalog from remote server: Error 500 on SERVER:
Server Error: Evaluation Error: Error while evaluating a Resource Statement,
Evaluation Error: Error while evaluating a Resource Statement, Duplicate
declaration: File[C:\Temp\tmp.txt] is already declared in file
/etc/puppetlabs/code/environments/production/manifests/site.pp:4; cannot redeclare
at /etc/puppetlabs/code/environments/production/manifests/site.pp:4
at /etc/puppetlabs/code/environments/production/manifests/site.pp:4:1
at /etc/puppetlabs/code/environments/production/manifests/site.pp:10 on node puppet-agent
As you can see, it claims that I have a duplicate declaration, but the weird thing is that it says it has a problem with the same line. It thinks it's declaring the same thing twice for some reason.
This is the code I have now (I know it won't work but the error doesn't really sound related)
define hosts_update($content) {
file { 'C:\Temp\tmp.txt' :
ensure => file,
content => $content,
}
}
hosts_update{ hiera('myhosts'):
content => split($name," "),
}
Any idea how to do this right?
fixed it.
site.pp
include update_hosts
init.pp
class update_hosts::host
(
$hosts = hiera('hosts_list'),
)
{
update_host { $hosts :; }
}
host.pp
define update_host {
​
$value = split($name,' ')
​
host {
"${value[0]}" : ip => "${value[1]}",
target => "C:/Windows/System32/drivers/etc/hosts"
}
}

Puppet; Call another .pp

So I am using the https://forge.puppetlabs.com/pdxcat/nrpe module to try to figure out automation of NRPE across hosts.
One of the available usages is
nrpe::command {
'check_users':
ensure => present,
command => 'check_users -w 5 -c 10';
}
Is there anyway to make a "group" of these commands and have them called on specific nodes?
For example:
you have 5 different nrpe:command each defining a different check, and then call those specific checks?
I am basically trying to figure out if I could group certain checks/commands together instead of setting up a ton of text in the main sites.pp file. This would also allow for customized templates/configurations across numerous nodes.
Thanks!
EDIT:
This is the command and what it's supposed to do when called on with the 'check_users' portion. If I could have a class with a set of "nrpe:command" and just call on that class THROUGH the module, it should work. Sorry, though. Still new at puppet. Thanks again.
define nrpe::command (
$command,
$ensure = present,
$include_dir = $nrpe::params::nrpe_include_dir,
$libdir = $nrpe::params::libdir,
$package_name = $nrpe::params::nrpe_packages,
$service_name = $nrpe::params::nrpe_service,
$file_group = $nrpe::params::nrpe_files_group,
) {
file { "${include_dir}/${title}.cfg":
ensure => $ensure,
content => template('nrpe/command.cfg.erb'),
owner => root,
group => $file_group,
mode => '0644',
require => Package[$package_name],
notify => Service[$service_name],
}
}
What version are you talking about? In puppet latest versions, inheritance is deprecated, then you shouldn't use it.
The easiest way would be to use "baselines".
Assuming you are using a manifests directory (manifest = $confdir/manifests inside your puppet.conf), simply create a $confdir/manifests/minimal.pp (or $confdir/manifests/nrpe_config.pp or whatever class name you want to use) with the content below:
class minimal {
nrpe::command { 'check_users':
ensure => present,
command => 'check_users -w 5 -c 10',
}
}
Then just call this class inside your node definitions (let's say in $confdir/manifests/my_node.pp) :
node 'my_node.foo.bar' {
include minimal
}

understanding repl in puppet code

I am looking at puppet code that looks something like
class {
users => {
'repl#%' => {
ensure => present,
.
}
}
}
What does "repl" do? I cant find much information online.
The amount of anonymization almost hides the important points. But I belive that this is supposed to be the declaration of a hash, meant for use with the create_resources function.
It works like this: If you have a large number of resources that should not take all the space in your class (this reason is contrived), you can convert it to a hash structure instead.
mysql_grant {
'repl#%':
ensure => present,
rights => 'REPLICATION CLIENT';
}
This becomes a hash, stored in a variable.
$users = {
'repl#%' => {
ensure => present,
rights => 'REPLICATION CLIENT',
}
}
This can then be used to declare this (and more resources in the hash, if there is more than one) in a simple line.
create_resources('mysql_grant', $users)
I'm guessing that you are looking at grants because repl#% is a typical MySQL notation that means user with name "repl" from any client.
TL;DR it is a domain specific identifier and has no special meaning to Puppet itself.

puppet, getting the $name when instantiating a resource type with an array

using puppet, i need to create three files, with this content:
/tmp/f1.txt: hello /tmp/f1.txt
/tmp/f2.txt: hello /tmp/f2.txt
/tmp/f3.txt: hello /tmp/f3.txt
i try as follows:
$path="/tmp/"
$my_files = ["$path/f1.txt", "$path/f2.txt", "$path/f3.txt"]
file { $my_files:
ensure => file,
content => "hello $name\n",
}
however this does not work because $name is undefined.
is there a variable that gets instantiated for each 'iteration' and that i can use?
ps: i am aware that i could create a new resource type as follows:
define file_with_content {
file { $name:
ensure => file,
content => "hello $name\n",
}
}
$path="/tmp/"
$my_files = ["$path/f1.txt", "$path/f2.txt", "$path/f3.txt"]
file_with_content { $my_files: }
but this requires creating a new resource type,
and I cannot do this in my context (which is not explained here).
the question is, how to modify the first code to make it work, without defining a new resource type, nor executing shell code?
You only can access the namevar for defined types. For Puppet's resources, the results are unpredictable - for example, $name for File will give you main, or the current stage. Additionally, you cannot pass/utilize extra parameters to Puppet's resources as they have their own set of parameters already.
The standard solution has been to wrap the File declaration in a defined type like here, like your first. Perhaps you can explain why that cannot be used, so some other solution could be devised?

Resources