Overriding a Puppet Class when using Inheritance - linux

I'm trying to use class inheritance for puppet. There is a base class named foo and an inherited class named bar. Overriding file or package resources are quite fine and works properly. But at the same time i'm using a custom module for configuring sudo.
The problem arises when i try to override sudo class from inside class bar. Puppet classes are as follows:
class foo {
$nrpe_plugin_pkgs = [ .... ]
service { 'nrpe service':
..
}
package { $nrpe_plugin_pkgs:
..
}
file { '/etc/nagios/nrpe.cfg':
..
}
file { '/etc/resolv.conf':
..
}
class { 'sudo':
purge => true,
config_file_replace => true,
}
sudo::conf { 'sudo_conf':
priority => 10,
content => [
'%gr1 ALL=(userfoo) NOPASSWD: ALL',
'%gr1 ALL=(root) NOPASSWD: /usr/bin/wbinfo *',
]
}
}
class bar inherits foo {
File['/etc/resolv.conf'] {
..
}
sudo::conf { 'sudo_conf':
priority => 10,
content => [
'%gr2 ALL=NOPASSWD:/bin/chown userbar\:gr2 /dirbar/*',
'%gr2 ALL=NOPASSWD:/bin/chown -R userbar\:gr2 /dirbar/*',
'%gr2 ALL=NOPASSWD:/bin/chmod * /dirbar/*',
]
}
}
I just want to customize only resolv.conf and sudo config, but i'm getting error as follows:
Error while evaluating a Resource Statement, Evaluation Error: Error
while evaluating a Resource Statement, Duplicate declaration:
Sudo::Conf[sudo_conf] is already declared in file
/etc/puppetlabs/code/environments/foobar_servers/manifests/foobar.pp:80;
cannot redeclare at
/etc/puppetlabs/code/environments/foobar_servers/manifests/foobar.pp:335
at
/etc/puppetlabs/code/environments/foobar_servers/manifests/foobar.pp:335:3
on node foobartest01
/etc/sudoers.d/10_sudo_conf file expected to be created. How can i achieve that?
Using: Puppet 4.9 Community version.
Any help appreciated.

The resolv.conf override works here, because you're using the correct syntax:
class bar inherits foo {
File['/etc/resolv.conf'] {
..
}
But the syntax for the next line where you try to override is different, so it fails:
sudo::conf { 'sudo_conf':
This is the syntax to declare a new resource (hence why you get a duplicate error) rather than to override an existing resource. It should be:
Sudo::Conf['sudo_conf'] {
priority => 10,
content => [
'%gr2 ALL=NOPASSWD:/bin/chown userbar\:gr2 /dirbar/*',
'%gr2 ALL=NOPASSWD:/bin/chown -R userbar\:gr2 /dirbar/*',
'%gr2 ALL=NOPASSWD:/bin/chmod * /dirbar/*',
]
}

Related

refactor ensure_packages to switch version of installed packages

I am successfully installing several PHP modules by version with puppet on Debian linux like this:
$php_version = '7.3'
ensure_packages([
"php$php_version-xml",
"php$php_version-zip",
"php$php_version-curl",
"php$php_version-mbstring",
"libapache2-mod-php$php_version",
],
{
'ensure' => 'present',
}
)
now I want to prepare for an update from PHP 7.3 to 7.4. This basically works, but the 7.3 packages stay installed. I would like to adapt the code to remove the old packages. I am looking for a way to reuse the list of packages of modules for uninstalling.
I am thinking of a signature like this
class profile::software::apache (
$php_version = '7.4',
$php_remove = ['7.0‘, ‘7.3'],
#...
) {
$myPackages = [
"php$php_version-xml",
"php$php_version-zip",
"php$php_version-curl",
"php$php_version-mbstring",
"libapache2-mod-php$php_version",
]
ensure_packages($myPackages,
{
'ensure' => 'present',
}
)
$php_remove.each | String $php_version | {
ensure_packages($myPackages,
{
'ensure' => 'absent',
}
)
}
}
Is there a way to solve this?
thx
I was able to solve this by using iteration functions of puppet.
From the two parameters I build a hash with keys of versions to work on and values to either install or remove the given version.
Now I can iterate over this hash with each, reusing the structure:
class profile::software::apache (
$php_version = '7.4',
$php_remove = ['7.0‘, ‘7.3'],
#...
) {
# build a hash of PHP Versions with a value of either present or absent
# and iterate over it with each
$phpInstallHash = { $php_version => 'present' }
#notify { "Value of phpRemove: ${php_remove}": }
if $php_remove {
# We have the array, use the map function to build remove hash
$phpRemoveHash = $php_remove.map |$version| {
{ $version => 'absent' }
}
$phpFullHash = $phpInstallHash + $phpRemoveHash
} else {
$phpFullHash = $phpInstallHash
}
#notify { "phpHash to iterate over to install/uninstall: ${phpFullHash}": }
#iterate over the result installing/uninstalling
$phpFullHash.each | $php_version, $ensure_value | {
ensure_packages([
"php$php_version-xml",
"php$php_version-zip",
"php$php_version-curl",
"php$php_version-mbstring",
"libapache2-mod-php$php_version",
],
{
'ensure' => $ensure_value,
require => [Class['apt::update'],
Apt::Source['source_php_sury'],
],
notify => Class['apache::service'],
}
)
}
}
hth

How to loop on a resource type multiple times in v3.8?

I have a Puppet manifest with three exec resources:
exec { 'test1':
command => "bla1",
require => File['test'],
}
exec { 'test2':
command => "bla2",
require => File['test'],
}
exec { 'test3':
command => "bla3",
require => File['test'],
}
Can someone offer a way to improve the code, such as with a loop?
I'm using Puppet 3.8 and would need something supported in that release.
This is one way to do it:
$cmd = [
"command1",
"command2",
"command3",
]
define run_command {
exec { "${name}":
path => ['/usr/bin','/usr/sbin','/bin','/sbin'],
}
}
run_command { $cmd:
require => File['test'];
}

pass array to the puppet resource defined

I would like to test if multiple packages exist in my environment or not, based on this test I would like to generate the final catalog.
if !defined( Package[ 'apache2' ] ) {
package { 'apache2':
ensure => installed,
}
}
if !defined( Package[ 'libapache2-svn' ] ) {
package { 'libapache2-svn':
ensure => installed,
}
}
In future I would like to control in the following way:
Package { ensure => "installed" }
$packageList = [ 'apache2', 'libapache2-svn' ]
if !defined( Package[ $packageList ] ) {
package { $packageList: }
}

Cannot parse array into defined type

I am using following puppet class
class myclass{
$foo = [{"id" => "bar", "ip" => "1.1.1.1"}, {"id" => "baz", "ip" => "2.2.2.2"}]
map {$foo:}
define map () { notify {$name['id']: } }
}
But this gives me
err: Could not retrieve catalog from remote server: Could not intern from pson: Could not convert from pson: Could not find relationship target "Change_config::Map[ip1.1.1.1idbar]"
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
What is the reason for this ?
Regards,
Malintha Adikari
Your array contains hashes. The resource declaration syntax works only for arrays of strings.
$foo = ["bar", "baz"]
map {$foo:}
define map () { notify {$name: } }
If you want to pass data with each resource title, you need to
build a hash of your data, not an array of hashes
use the create_resources function
Untested example code:
$foo = {
"bar" => { "ip" => "1.1.1.1" },
"baz" => { "ip" => "2.2.2.2" },
}
create_resources('map', $foo)
define map ($ip="") { notify { "$name has ip $ip": } }

Can I write duplicate node blocks in Puppet site.pp file?

I am trying to write duplicate node blocks in site.pp file. This site.pp file I am generating from Java code. When I do test 'puppetd --test' I am not getting other node blocks changes on client.
site.pp
node "puppetclient1.domain.com" {
file { "twc-bind-9.9.4-0.noarch.rpm" :
source => "puppet:///files/modules/BIND/twc-bind-9.9.4-0.noarch.rpm",
}
}
node "puppetclient1.domain.com" {
package { "twc-bind" :
source => "/opt/test/files/twc-bind-9.9.4-0.noarch.rpm",
provider => "rpm",
ensure => "latest",
}
}
node "puppetclient1.domain.com" {
service { "named" :
subscribe => File["/opt/test/files/twc-bind-9.9.4-0.noarch.rpm"],
ensure => "running",
}
}
I'm pretty sure that puppet will match against the first node it finds.
You need to make your Java code a little bit smarter and add all of the resources into a single node, i.e.
node "puppetclient1.domain.com" {
file { "twc-bind-9.9.4-0.noarch.rpm" :
source => "puppet:///files/modules/BIND/twc-bind-9.9.4-0.noarch.rpm",
}
package { "twc-bind" :
source => "/opt/test/files/twc-bind-9.9.4-0.noarch.rpm",
provider => "rpm",
ensure => "latest",
}
service { "named" :
subscribe => File["/opt/test/files/twc-bind-9.9.4-0.noarch.rpm"],
ensure => "running",
}
}
Or another option would be to use node inheritance.
If you'll have to deal with hundred of resources and thousands of boxes, you should care about make a good design and modeling. Put your resources into classes, and then classes into more general classes and then, put classes into boxes. And use hiera or parameterized classes or both to change resources
class twc-bind {
file { "/opt/test/files/twc-bind-9.9.4-0.noarch.rpm" :
source => "puppet:///files/modules/BIND/twc-bind-9.9.4-0.noarch.rpm",
}
package { "twc-bind" :
source => "/opt/test/files/twc-bind-9.9.4-0.noarch.rpm",
provider => "rpm",
ensure => "latest",
}
service { "named" :
ensure => "running",
}
File["twc-bind-9.9.4-0.noarch.rpm"]->Package["twc-bind"]->Service["named"]
}
node "puppetclient1.domain.com" {
class { "twc-bind" :
}
}
If you're using Java to generate manifests, you shuold model your Java classes too.

Resources