PuppetModulesCookbook - henk52/knowledgesharing GitHub Wiki

Table of Contents

Introduction

Purpose

Scope

References

Acronyms

See:

Combining - local combination of multiple classes

I couldn't find a way to make a module server multiple "masters", I need to have a "parent" module to rule the whole thing.

So if I want to install multiple modules that all uses e.g. a web server, then the parent module needs to know what each of the modules needs of alias directories.

Cookbook

Modules

Create a new module

  1. create your project on https://github.com
  2. puppet module generate reidmv-motd
  3. mv reidmv-motd reidmv-motd.org
  4. git clone xxx
  5. cd reidmv-motd.org
  6. mv * ../reidmv-motd
  7. cd ../reidmv-motd
  8. git add xxx
  9. git commmit -m "Some great comment."
  10. cd ..
  11. sudo mv reidmv-motd /etc/puppet/modules/motd

Testing the new module

See: http://puppetlabs.com/blog/verifying-puppet-checking-syntax-and-writing-automated-tests

  1. puppet-lint manifests/init.pp
  2. puppet-lint tests/init.pp
  3. sudo puppet parser validate manifests/init.pp
  4. sudo puppet parser validate test/init.pp
  5. sudo puppet apply test/init.pp --noop

External modules

rspec

Installing the RSPEC app

Create the rspec structure in your module

Releasing your module

Dependencies

require multiple resources

user { "tim":
  ensure => present,
  gid => "fearme",
  groups => ["adm", "staff", "root", "fearmenot"],
  membership => minimum,
  shell => "/bin/bash",
  require => [ Group["fearme"],
               Group["fearmenot"]
             ]
}

See: https://ask.puppetlabs.com/question/3339/require-a-subclass/

It looks like you are using a defined type called apt::ppa, so you would need to capitalize all the words of the type:

require => Apt::Ppa['ppa:git-core/ppa'],

If you were declaring a class called apt::ppa, you would want to require the class:

require => Class['apt::ppa'], 
lvm::volume { 'kickstart':
  ensure => present,
  vg => 'vg_images',
  pv => '/dev/sda5',
  fstype => 'ext4',
  size => '10G',
}

file { '/var/ks':
  ensure => directory,
}
/dev/vg_images/kickstart

file_line { 'kickstart_dir':
  path => '/etc/fstab',
  line => '/dev/vg_images/kickstart /var/ks ext4 defaults 1 2',
  require => [ 
        File['/var/ks' ],
        Lvm::Volume[ 'kickstart' ],
             ],
} 

Manifest operations

File

Templating

creating a file from a template

See: https://github.com/puppetlabs/puppetlabs-motd/blob/master/manifests/init.pp

file { '/etc/motd':
  ensure  => file,
  backup  => false,
  content => template('motd/motd.erb'),
}

Making the template file relative to the module

To make use a template delivered with your module you need to add the module name as a relative path to the template name.

I think the module is expected to be installed in '/etc/puppet/module' or another officially configured path.

content => template('motd/motd.erb'), Would expect to find the 'motd.erb' in /etc/puppet/modules/motd/templates/motd.erb

inline_template

$arRepoAdmPublicKeys = hiera('repoadmpubkeys')

file { '/home/repoadm/.ssh/authorized_keys':
  ensure  => file,
  owner   => 'repoadm',
  mode    => '700',
  content => inline_template("<% @arRepoAdmPublicKeys.each do |szKey| -%>
<%= szKey %>
<% end %>"),
  require => File['/home/repoadm/.ssh'],
}

Passing data to templates

file_line

  • You need to install the puppetlabs-stdlib module.
See: https://ask.puppetlabs.com/question/14366/file_line-resource-match-problems/
sonar.jdbc.username=sonar

file_line { 'sonar_username':
  path => '/opt/sonar/conf/sonar.properties',
  line => 'sonar.jdbc.username=sonar',
  match => '^.sonar.jdbc.username=',
}
sonar.jdbc.password=sonar

file_line { 'sonar_password':
  path => '/opt/sonar/conf/sonar.properties',
  line => 'sonar.jdbc.password=sonarpasswd',
  match => '^.sonar.jdbc.password=',
}

sonar.jdbc.url=jdbc:postgresql:

file_line { 'sonar_postgresql':
  path => '/opt/sonar/conf/sonar.properties',
  line => 'sonar.jdbc.url=jdbc:postgresql://localhost/sonar',
  match => '^.sonar.jdbc.url=jdbc:postgresql:',
} 

Augeas

change grub.cfg with augeas

See also: http://serverfault.com/questions/554092/how-to-update-grub-with-puppet

augeas { 'hyperthread_enable':
 context => '/files/etc/default/grub',
 changes => [ 'set GRUB_CMDLINE_LINUX \'"\"noapic vconsole.font=latarcyrheb-sun16 selinux=0 $([ -x /usr/sbin/rhcrashkernel-param ] && /usr/sbin/rhcrashkernel-param || :) acpi=ht rhgb quiet\""\'', ], notify => Exec['grub-update'], }'set GRUB_CMDLINE_LINUX "\"noapic vconsole.font=latarcyrheb-sun16 selinux=0 \$([ -x /usr/sbin/rhcrashkernel-param ] && /usr/sbin/rhcrashkernel-param || :) acpi=ht rhgb quiet\""',
  exec { 'grub-update': refreshonly => true, command => '/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg', 
}

Manifest variables

Hash

Hash of Hashes created in hieara

See also: https://docs.puppetlabs.com/hiera/1/data_sources.html

netconfig:
 vnic02:
  nic_name: eth2
  ip_addr: 10.1.2.3
  netmask: 255.255.255.0
 vnic03:
  nic_name: eth3
  ip_addr: 10.1.3.3
  netmask: 255.255.255.0
 vnic04:
  nic_name: eth4
  ip_addr: 10.1.4.3
  netmask: 255.255.255.0 

Hash of hashes created in manifest

$netconfigs = { 
  vnic02 => { nic_name => 'eth2', ip_addr => '10.1.2.3', netmask => '255.255.255.0', },
  vnic03 => { nic_name => 'eth3', ip_addr => '10.1.3.3', netmask => '255.255.255.0', },
  vnic04 => { nic_name => 'eth4', ip_addr => '10.1.4.3', netmask => '255.255.255.0', }, 
}

Hash of hashes used in manifest

See: https://ask.puppetlabs.com/question/724/iterate-nested-hash-from-hiera-in-manifest/

define notify_netconfigs($nic_name, $ip_addr, $netmask) { notify { "currently looping NIC: $nic_name, $ip_addr, $netmask": } }
$netconfigs = hiera("netconfig") create_resources( notify_netconfigs, $netconfigs ) 

Hash of hashes used in template

<% @netconfigs.each do |hNetConfigSet| -%> Data ( "<%= hNetConfigSet['ip_addr'] %>" => "<%= hNetConfigSet['netmask'] %>" ) <% end %>

Array

facts in manifests

    $operatingsystem will give you the content from the fact of that name.

manifest variable handling

Convert a string to an array

See: https://ask.puppetlabs.com/question/3540/split-string-into-multiple-variables/ $arInterfaceList = split($interfaces, ',') $szSecondInterface = $arInterfaceList[1] setting a new value if the class parameter wasn't set

class server-of-diskless-boot { 
  $szNetworkInterfaceName = hiera( 'NetworkInterfaceName', '' ), 
  $szServiceIpAddress = hiera( 'ServiceIpAddress', '172.16.1.3' ), ) {
  #if $szNetworkInterfaceName not set then set it 
  if ( $szNetworkInterfaceName == '' ) { 
    # # Facter: interfaces (Array of interfaces), grab the second entry.
    notify{ "Network interface name not set.": } 
    $arInterfaceList = split($interfaces, ',')
    $szNicName = $arInterfaceList[1] 
  } else { 
    $szNicName = $szNetworkInterfaceName 
  }
  notify{ "NIC: $szNicName ( $szServiceIpAddress )": }
} # end class.

manifest network configuration

Static IP

See: https://forge.puppetlabs.com/razorsedge/network

network::if::static { "$szNicName": ensure => 'up', ipaddress => "$szServiceIpAddress", netmask => '255.255.255.0', }

general module information

meta parameters

See also: http://docs.puppetlabs.com/guides/techniques.html

  • before - applied to be applied before the target resource
  • require - applied after the target resource
The above relationship can also be defined using '->'
    like in: Package['openssh-server'] -> File['/etc/ssh/sshd_config] This means that: Package must be installed before the File can be ensured/created."
  • notify - happens before and send a refresh i the resource is changed.
  • subscribe The above relationship can also be defined using '~>'
        like in: File['/etc/ntp.conf'] ~> Service[ntpd] This means that: "Service will be notified when the File is updated."

inheritance

  • Use it sparingly since it very easily can cause breakage.
  • Only useful for overriding resource attributes[01-1105].
  • any other use case is better accomplished with other methods.
  • relationship override - Use a single class with conditional relationship declarations.

Variable

  • $variables always start with a dollar sign. You assign to variables with the = operator.
  • Variables can hold strings, numbers, booleans, arrays, hashes, and the special undef value.
  • If youʼve never assigned a variable, you can actually still use it — its value will be undef.
  • You can use variables as the value for any resource attribute, or as the title of a resource.
  • Every variable has two names:
  • A short local name: `$variable
  • If you reference a variable with its short name and it isnʼt present in the local scope, Puppet will also check the global top scope.
  • A long fully-qualified name $scope::variable
  • Always use the fully-qualified, the $::variable notation, when referring to facts. To avoid confusion or doubt.
  • You can only assign the same variable once in a given scope. In this way, theyʼre more like constants from other programming languages.

RPM your module

    https://fedoraproject.org/wiki/How_to_create_an_RPM_package?rd=PackageMaintainers/CreatingPackageHowTo
    https://fedoraproject.org/wiki/How_to_create_a_GNU_Hello_RPM_package
    Manifest

See the cookbook at: http://www.puppetcookbook.com/posts/run-exec-if-file-absent.html

    exec
        http://www.puppetcookbook.com/posts/run-exec-if-file-absent.html
    Installing local gem packages
        http://blog.moertel.com/posts/2007-11-15-a-couple-of-tips-for-writing-puppet-manifests.html

Services

Enable xinet service - rsh

See: http://linoxide.com/how-tos/howto-enable-rshrlogin-on-linux-server/

 package { 'rsh-server': ensure => present, }

augeas { 'rsh_enable': context => '/files/etc/xinetd.d/rsh', changes => [ 'set service/disable "no"', ], require => Package [ 'rsh-server' ], notify => Service['xinetd'], }

service { 'xinetd': ensure => running, enabled => true, }

Installation

Multiple packages Grab a file from an external source

exec { 'get_VBoxLinuxAdditions_run': 
  creates => '/var/puppetextras/VBoxLinuxAdditions.run', 
  command => '/usr/bin/wget --directory-prefix=/var/puppetextras http://10.1.233.3:/storage/puppet/VBoxLinuxAdditions.run', 
  require => File [ '/var/puppetextras' ], 
}

Install a special application package

exec { 'install_VirtualBoxAdditions': 
  creates => '/opt/VBoxGuestAdditions-4.3.18', 
  command => '/var/puppetextras/VBoxLinuxAdditions.run', 
  require => File [ '/var/puppetextras/VBoxLinuxAdditions.run' ], 
}

user
generate a password thingy
host ops
Change the host name and domain

See: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html
file_line { 'hostname':
  path => '/etc/sysconfig/network', 
  line => 'HOSTNAME=host.domain', 
  match => '^HOSTNAME=*', 

}

Class

See: * puppet class parameters * http://docs.puppetlabs.com/puppet/latest/reference/lang_classes.html

Class parameters

Creating a Class with parameters Class with a single parameter

See: http://docs.puppetlabs.com/puppet/latest/reference/lang_classes.html class apache ($version = 'latest') { package {'httpd': ensure => $version, # Using the class parameter from above before => File['/etc/httpd.conf'], } } Provide a default value to a parameter Defaulting a parameter to a default value, in Hiera

class lighttpd ( $szWebProcessOwnerName = hiera( 'WebProcessOwner', 'lighttpd' ), $szWebRootDirectory = hiera( 'WebRootDirectory', '/var/www' ) ) inherits lighttpd::params { ... } Transfer parameters in class instantiation Hash, class parameters

The Class header: class lighttpd ( $szWebProcessOwnerName = hiera( 'WebProcessOwner', 'lighttpd' ), $szWebRootDirectory = hiera( 'WebRootDirectory', '/var/www' ), $harAliasMappings ) inherits lighttpd::params { ... }

The Template usage: <% @harAliasMappings.each_pair do |szAlias, szDirectory| -%> * <%= szAlias %>: <%= szDirectory %> <% end %>

The caller definition: ``` $arAliases = { 'git' => '/var/git', 'test' => '/var/test', }

class { "lighttpd": harAliasMappings => $arAliases, } ``` Default parameter values modify a line in a file

sonar.jdbc.url=jdbc:postgresql:

file_line { 'set_sonar_db_postgresql': 
  path => "$SONARRUNNER_CONF", line => 'sonar.jdbc.url=jdbc:postgresql://localhost/sonar',
  match => '^.sonar.jdbc.url=jdbc:postgresql:', 
  require => Exec [ 'install_sonar' ], 
} 

Hiera

Configuration of Hiera

From Listing 12.8 in 'Pro Puppet'

  1. sudo mv /etc/hiera.yaml /etc/puppet/hiera.yaml
  2. sudo ln -s /etc/puppet/hiera.yaml /etc/hiera.yaml
  3. sudo mkdir /etc/puppet/data
  4. sudo vi /etc/puppet/hiera.yaml
    • add: :datadir: /etc/puppet/data
  5. sudo vi /etc/puppet/data/defaults.yaml
    • ---
    • IpAddressForSupportingKickStart: '10.1.233.3'
    • hiera IpAddressForSupportingKickStart

Lookup missing values in Hiera

File operations

LVM

mounting

https://awaseroot.wordpress.com/2012/11/03/puppet-module-for-etcfstab-mounts/

mount { '/var/ks':

    device => '/dev/vg_images/kickstart', fstype => 'ext4', ensure => mounted, options => 'defaults',
        atboot => true, require => [
            File ['/var/ks' ], Lvm::Volume'kickstart' , ],

}

Testing

rspec

Modules in action

Network configuration

razorsedge/network

For configuring the network interfaces.

See: https://forge.puppetlabs.com/razorsedge/network Virtual machine preparation/installs

files

# ---------------------------------------------------------------------
# ------------------------
sub GetFile { 
  my $szHttpBaseSource = shift; 
  my $szLocalDestination = shift; 
  my $szFileName = shift;

  if ( ! -f "$szLocalDestination/$szFileName" ) { 
    cd $szLocalDestination; wget $szHttpBaseSource/$szFileName; 
  }
}

#---------------------------------------------------------------------
#------------------------
sub GetAndDeployModuleTgz { 
  my $szPuppetPackageName = shift;
  my $szPuppetModuleName = shift;

  GetFile($f_szHttpBaseSourcePuppet, $f_szLocalDestination, "$szPuppetPackageName.tar.gz");

  if ( ! -e "/etc/puppet/modules/$szPuppetModuleName" ) {
    print "III Installing the $szPuppetPackageName module.\n"; 
    cd /etc/puppet/modules; tar -zxf $f_szLocalDestination/${szPuppetPackageName}.tar.gz; 
    cd /etc/puppet/modules; ln -s $szPuppetPackageName $szPuppetModuleName; 
  }
} 

Trouble shooting

Error: Evaluation Error: Error while evaluating a Resource Statement, Invalid resource type file_line at

  1. dnf install puppetlabs-stdlib
  2. ln -s /usr/share/puppet/modules/stdlib /etc/puppet/modules/stdlib
Error: Evaluation Error: Error while evaluating a Resource Statement, Invalid resource type file_line at /root/install_ntp.pp:10:1 on node localhost
⚠️ **GitHub.com Fallback** ⚠️