Puppet; Call another .pp - puppet

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
}

Related

Puppet assign class parameters in multiple places

I'm learning puppet (v6), and trying to understand how to set class parameters when a specific node needs an additional parameter, but uses the same class. Maybe a little fuzzy on the terminology, but here's what I'm working on:
MyNode1 needs sshd configured to use a banner and timeout, so using ghoneycutt-ssh, I include the ssh class with parameters:
/modules/MyModule/manifests/MySSH.pp
# Configures SSH
class MyModule::MySSH {
# Using ssh module
class { '::ssh':
sshd_client_alive_count_max => 0,
sshd_client_alive_interval => 900,
sshd_config_banner => '/etc/MyBanner.txt',
}
}
Now I have a second node MyNode2, which requires MySSH above, and also needs to disable forwarding. I started with something like this, where I define only the additional parameter in its own class:
/modules/MyModule/manifests/MySSH_Node2.pp
class MyModule::MySSH_Node2 {
class { '::ssh':
sshd_allow_tcp_forwarding => 'no',
}
}
Then define MyNode2 to include both in my site definition, hoping that puppet merges my ::ssh definitions:
/manifests/site.pp
node MyNode1 {
include MyModule::MySSH
}
node MyNode2 {
include MyModule::MySSH
include MyModule::MySSH_Node2
}
I understand that the above example doesn't work due to error Duplicate declaration: Class[Ssh]. I also tried overriding the class with a new parameter:
class MyModule::MySSH_Node2 {
Class[ssh] {
sshd_allow_tcp_forwarding => 'no',
}
}
But it seems this is not allowed either: Error: Resource Override can only operate on resources, got: Class[ssh]-Type
I'm not sure what the best way to add parameters is. I know I can create a manifest that includes all the parameters needed for this node and apply that instead, but then I end up with duplicate code everywhere.
Is there a reasonable way in modern puppet to assign and merge class parameters like this in puppet?

Assign variable from hiera as username (with uid and gid) inside puppet class

Hello Community members,
We have a puppet file which has a main class like below:
class profile::Profname::application::classname {
$appname_homedir = hiera('appname::appname_homedir')
$appname_installdir = hiera('appname::appname_installdir')
$java_optional_args = "${java_keystore_args} ${java_proxy_args} ${java_timezone_args}"
..
..
$user = hiera('appname::appname_user')
$gid = hiera('appname::appname_user_gid')
$uid = hiera('appname::appname_user_uid')
exec { "Many blocks":
command => "commands",
..
}
exec { "Many blocks":
command => "commands",
..
}
# Install and configure app
class { 'app':
user => hiera('classname::appname_user'),
jvm_opts => $java_optional_args,
download_url => "s3://${s3_bucket}/${APPDIR}/appname",
dbserver => hiera('appname::db-endpoint'),
notify => Exec["Change appname gid and uid"],
require => [ Class['java'], Exec['Create Homedir'], Exec['Create Appdir']],
}
#other exec blocks
exec { "blocks"
..
..
}
}
Now I have two more variables in hiera those are: uid and gid for the appname_user.
How can I create the user "appname_user" in the inner class 'app'?
I was trying to refer https://puppet.com/docs/puppet/4.10/quick_start_user_group.html but not sure how can I do this inside the inner class. Any help would be greatly appreciated.
I did another exec block of changing the uid and gid for the user later when user is created but that way does not seem to be working for some files already present. Though puppet execution is successful. Hence I want to create the user with uid, and gid at the time of creation.
Thanks and Regards,
Saha
How can I create the user "appname_user" in the inner class 'app'?
My best guess is that you mean within this construct:
class { 'app':
user => hiera('classname::appname_user'),
jvm_opts => $java_optional_args,
download_url => "s3://${s3_bucket}/${APPDIR}/appname",
dbserver => hiera('appname::db-endpoint'),
notify => Exec["Change appname gid and uid"],
require => [ Class['java'], Exec['Create Homedir'], Exec['Create Appdir']],
}
The answer to that is simple: you can't. But there is a variety of related things you could do.
First things first: "inner class" is not a term used in Puppet. There can be nested classes, but
that's not what you have presented, and
nesting classes is widely regarded as poor style.
What you have shown is a declaration of class app inside the definition of class profile::Profname::application::classname. A class declaration, when evaluated, tells Puppet to include the designated class in the catalog then under construction, and it optionally binds values to some that class's parameters. There must be a definition of the class elsewhere to tell Puppet what that means. If you want it to declare a resource that it does not already declare, then it is the definition that must be modified.
You would typically manage a user by declaring a User resource (inside one class definition or another). In your case, you could find the definition of class app and put it there, but you could also put it in your profile class, alongside the existing declaration of class app. Which one would serve you best depends on what you're trying to accomplish.

How to work around vcsrepo "duplicate declaration" evaluation error?

I am installing from github using puppet-vcsrepo. The code looks something like this:
class demo_class(
$my_repo = undef,
$my_tag = undef,
){
vcsrepo { "$my_repo",
path => "/home/user/$my_repo",
source => 'git#github.com:7yl4r/$my_repo.git',
ensure => latest,
provider => git,
}
# then declare resources specific to my_tag
}
This works just fine when called only once, but I am iterating over a list and installing dependencies so this resource sometimes gets declared twice. I think this is roughly equivalent to the code below.
class {"demo_class":
my_repo => test_repo,
my_tag => test_tag1,
}
class {"demo_class":
my_repo => test_repo,
my_tag => test_tag2,
}
Doing this yields a server-side "Duplicate declaration" error because vcsrepo is trying to map the the same path twice. However, this is exactly the behavior I want: for both resources declared by demo_class to require the same repo in the same location. This is so that I can declare one or more resources using demo_class and be sure the repo given by my_repo (which may be common to multiple my_tags) is there.
How can I modify this class so that I can call it twice without hitting an error?
I see the problem.
I reproduced the issue using this code:
define my_vcs_repo ($myRepo, $myTag) {
vcsrepo { "$myRepo-$myTag":
path => "/home/user/$myRepo",
source => "git#github.com:7yl4r/$myRepo.git",
revision => $myTag,
ensure => latest,
provider => git,
}
}
$data = [
{
myRepo => testRepo,
myTag => testTag1,
},
{
myRepo => testRepo,
myTag => testTag2,
},
]
$data.each |$i, $ref| {
$myRepo = $ref['myRepo']
$myTag = $ref['myTag']
my_vcs_repo { "$myRepo-$i":
myRepo => $myRepo,
myTag => $myTag,
}
}
That then results in:
Puppet::PreformattedError:
Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Error while evaluating a Resource Statement, Cannot alias Vcsrepo[testRepo-testTag2] to ["/home/user/testRepo"] at /
Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/manifests/init.pp:3; resource ["Vcsrepo", "/home/user/testRepo"] already declared at /Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/
manifests/init.pp:3 at /Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/manifests/init.pp:3:5 at /Users/alexharvey/git/modules/foo/spec/fixtures/modules/foo/manifests/init.pp:26 on node alexs-macbook-pro.local
The problem is that you are asking Puppet to clone the same Git module to a directory but with two different tags checked out. That does not make sense.
The fix is that you need to specify a unique path in the vcsrepo path attribute, e.g.:
vcsrepo { "$myRepo-$myTag":
path => "/home/user/$myRepo-$myTag",
source => "git#github.com:7yl4r/$myRepo.git",
revision => 'production',
ensure => latest,
provider => git,
}
By the way, I notice you are using camelCase for your variables. Don't do that. Aside from the fact that it is not idiomatic for Puppet, there are things that will break in some versions of Puppet/Rspec puppet that I have seen.
Use snake_case for your variable names and class parameter names.
Update
The question has been edited, and it is now a question about how to declare the same vcsrepo in more than one class.
In general, try to refactor so that you do not need to do this in the first place. In other words, just move it out of this class and put it somewhere that is only expected to be declared once.
If you cannot do this for some reason, then you can also use virtual resources, which will allow you to declare it in multiple classes that will be declared on the same node.
To do that, you just have to rewrite what you have there as:
#vcsrepo { $my_repo:
path => "/home/user/$my_repo",
source => "git#github.com:7yl4r/$my_repo.git",
ensure => latest,
provider => git,
}
realize Vcsrepo[$my_repo]
Keep in mind that you will not be able to declare the class demo_class twice on the same node either. You would need to turn it into a defined type, as I did above.
It is mentioned in the comments below that you can also use ensure_resource and ensure_resources; see docs in stdlib.

puppet 4.7 - how can I execute something at the end of a run?

I need to execute something as the very last thing of a puppet apply run. I tried to do that by defining a stage 'last', but the syntax restrictions on declaring a class in resource mode are a problem.
Is there a good way to use stages like this? Or is there some other way to make sure some class is executed last?
for example, this gives me an error for a duplicate declaration(sometimes, and I'm not sure why at this point):
class xyz::firstrun {
exec { 'exec_firstrun':
onlyif => '/usr/bin/test -e /tmp/firstrun.sh',
command => '/tmp/firstrun.sh',
path => ['/usr/bin/','/usr/sbin'],
creates => '/tmp/firstrun.done',
}
}
class { 'xyz::firstrun':
stage => last,
}
Sometimes, the firstrun class runs without error, but in the main stage.
I'm not a big fan of run stages, but they are the the right tool for this job. It's a bit unclear exactly what gives you the duplicate declaration error you describe, but if, for example, your class definition and class declaration both appear in the same file, then that might be a problem.
Here's how a solution using run stages might look:
environments/production/modules/site/manifests/stages.pp
class site::stages {
stage { 'last':
# Stage['main'] does not itself need to be declared
require => Stage['main'],
}
}
environments/production/modules/xyz/manifests/firstrun.pp
class xyz::firstrun {
exec { 'exec_firstrun':
onlyif => '/usr/bin/test -e /tmp/firstrun.sh',
command => '/tmp/firstrun.sh',
path => ['/usr/bin/','/usr/sbin'],
creates => '/tmp/firstrun.done',
}
}
environments/production/manifests/nodes.pp
node 'foobar.my.com' {
include 'site::stages'
include 'something::else'
# Must use a resource-like declaration to assign a class to a stage
class { 'xyz::firstrun':
stage => 'last'
}
}
Note that although include-like class declarations are generally to be preferred, you must use a resource-like declaration to assign a class to a non-default stage. You must therefore also be careful to avoid declaring such classes more than once.
You can use puppet relationship and ordering to do this.
(1) If you want to execute the entire class at the end, you can include your class in init.pp and user ordering arrow (->) to execute it after all other classes.
example:
file: /etc/puppet/modules/tomcat/init.pp
class tomcat {
include ::archive
include ::stdlib
class { '::tomcat::tomcatapiconf': }->
class { '::tomcat::serverconfig': }
}
(2) If you want a specific resource in a class to execute at the end, you can use the same arrow (->) within the class or use before or require in the resource
example:
file { '/etc/profile.d/settomcatparam.sh':
ensure => file,
before => File_line['/etc/profile.d/settomcatparam.sh'],
}
file_line { '/etc/profile.d/settomcatparam.sh':
path => '/etc/profile.d/settomcatparam.sh',
ine => 'export LD_LIBRARY_PATH=/usrdata/apps/sysapps/apr/lib:/usrdata/apps/sysapps/apr-util/lib:/usrdata/apps/sysapps/tomcat-native/lib:$LD_LIBRARY_PATH',
}
OR
exec { 'configure apr-util':
cwd => "/tmp/apr-util-${tomcat::aprutilversion}/",
command => "bash -c './configure --prefix=/usrdata/apps/sysapps/apr-util --with-apr=/usrdata/apps/sysapps/apr'",
} ->
exec { 'make apr-util':
cwd => "/tmp/apr-util-${tomcat::aprutilversion}/",
command => 'make',
}
You can also use combination of before, require and ->. Just make sure you don't create a dependency cycle.

Instantiating a class for each item in an array

Puppet Version: 3.2.4 (Puppet Enterprise 3.0.1)
In order to better support nagios cfg_dir and cfg_file directives in the config file, I've created the following class(es), one for each option:
# Class to add a cfg_dir to the nagios configuration file
class nagios::server::cfg_dir (
$config_dir,
$nagios_user,
$nagios_group,
$nagios_config_file = '/etc/nagios3/nagios.cfg',
)
{
# Build the config dir
file {$config_dir:
ensure => directory,
owner => $nagios_user,
group => $nagios_group,
mode => '0750',
}
# Append cfg_dir=$config_dir path to nagios.cfg file
augeas { "cfg_dir=$config_dir in $nagios_config_file":
incl => "$nagios_config_file",
lens => 'NagiosCfg.lns',
changes => "set cfg_dir/[last()+1] ${config_dir}",
require => File[$nagios_config_file],
}
}
Trying to use this construct inside nagios::server, I have this:
# Set up config directories
each($cfg_dir) |$x| {
class { 'nagios::server::cfg_dir':
config_dir => $x,
nagios_user => $nagios_user,
nagios_group => $nagios_group,
nagios_config_file => $nagios_config_file,
}
}
Which should, in theory, execute the class instantiation for each path passed in to the nagios::server class like so:
class{'::nagios::server': cfg_dir => ['/etc/nagios.d','/etc/nagios/objects'] }
However, I run into this issue:
Error: Could not match |$x| at /tmp/vagrant-puppet-1/modules-2/nagios/manifests/server.pp:181 on node localhost.localdomain
Can someone provide a working example of each in use? Am I expecting too much from this built-in puppet function?
Aside from a few of the code grammar issues above, I've found that this construct is only evaluated in the future parser:
puppet apply --parser=future --modulepath ...
http://docs.puppetlabs.com/puppet/latest/reference/experiments_lambdas.html
Still getting past other dependency issues. What pattern would I use to support this with the current parser instead of future? A custom function?
The answer to my follow-up question is to use defined types:
http://docs.puppetlabs.com/learning/definedtypes.html
Simply changing the above code from a class to a define and assign $config_dir the value from $target,
define nagios::server::cfg_dir (
$config_dir = $target,
$nagios_user,
$nagios_group,
$nagios_config_file = '/etc/nagios3/nagios.cfg',
){...
you can use constructs such as:
nagios::server::cfg_dir { '/etc/nagios.d/', '/etc/nagios/objects':
nagios_user => 'nagios',
nagios_group => 'nagios'
}
This solves the issue for me.

Resources