Showing posts with label Puppet. Show all posts
Showing posts with label Puppet. Show all posts

Wednesday, January 9, 2013

Puppet Template : Loop with multiple variables


Is @path supposed to be the same for each user? If so, you can just put that variable in the block.
<% @users.each do |user| %>
    /bin/mount --bind <%= @path %> /home/<%= user %>
<% end %>

If each user has a path value unique to them, following are some ways to achieve it.

Solution1 : 
(in Puppet class)
$mountpoints = { 
      'user1' => '/home/some/path', 
      'user2' => /home/another/path'
}
(in Puppet template)
<% mountpoints.each do |user, path| -%>
/bin/mount --bind <%= path %> /home/<%= user %>/www 
<% end -%>

Solution2 :  you might want to put that in an array of hashes and then iterate over that like this:

(in Puppet class)
$users = [ { name => 'alice', path => '/alice/path' }, 
           { name => 'bob', path => '/bob/path' } ]
(in Puppet template)
<% @users.each do |user| %>
    /bin/mount --bind <%= user['path'] %> /home/<%= user['name'] %>
<% end %>


Defining custom function to generate Array of Hash

Function  :
test-module/lib/puppet/parser/functions/produceArray.rb
module Puppet::Parser::Functions
    newfunction(:producearray, :type => :rvalue) do |args|  

        serverArray  = args[0].split(",")
        propArray    = args[1].split(",")

        myarray = []
        serverArray.each do |obj|
            i  = 0
            myServer = Hash.new
            obj.split(":").each do |prop|
                myServer[propArray[i]] = prop
                i = i+1
            end
            myarray.push(myServer)
        end
        return myarray
    end

end


Manifest :
test-module/manifests/init.pp
$serverlist1  = producearray("10.176.40.171:8080,10.183.32.157:8081","ip,port")
$serverlist2  = producearray("10.176.40.171:8080:password1,10.183.32.157:8081:password2","ip,port,password")

file {'/usr/local/templateOutput' :
    ensure => present,
    content => template("test-module/template.erb"), 
}

Template :
test-module/templates/template.erb

<% for @server in @serverlist1 %>
{
    Ldap Ip : <%= @server['ip'] %> 
    Ldap Port :<%= @server['port'] %>
}
<% end %>
.................
<% for @server in @serverlist2 %>
{
    Ldap Ip : <%= @server['ip'] %> 
    Ldap Port :<%= @server['port'] %>
    Ldap password :<%= @server['password'] %>
}
<% end %>


Output :
/usr/local/templateOutput
{
        Ldap Ip : 10.176.40.171
        Ldap Port :8080
}
{
        Ldap Ip : 10.183.32.157
        Ldap Port :8081
}
.................
{
        Ldap Ip : 10.176.40.171
        Ldap Port :8080
        Ldap password :password1
}
{
        Ldap Ip : 10.183.32.157
        Ldap Port :8081
        Ldap password :password2
}

Configure Puppet Master for supporting mullitiple environment

In the last blog which features installing and configuring  Puppet  with LDAP  as configuration store here .

With an assumption that Puppet master and client were successfully installed and SSL certificate has been signed, I have shown how to configure Puppet Master  for serving  different puppet recipes  ( modules and manifest ) to different environment (development , testing and production etc)

Note : Environments were introduced in Puppet 0.24.0.

What an Environment is  :

Puppet lets you slice your site up into an arbitrary number of “environments” and serve a different set of modules to each one. This is usually used to manage releases of Puppet modules by testing them against scratch nodes before rolling them out completely, but it introduces a lot of other possibilities, like separating a DMZ environment, splitting coding duties among multiple sysadmins, or dividing the site by hardware type.

Note : In our development , we are using environment variable to support multiple releases to puppet client.

Every client node has an environment, and the puppet master gets informed about it whenever that node makes a request. (If you don’t specify an environment, the puppet client has the default “production” environment.)

The puppet master can then use that environment several ways:
  • If the master’s puppet.conf file has a [config block] for this agent’s environment, those settings will override the master’s normal settings when serving that agent.
  • If the values of any settings in puppet.conf reference the $environment variable (like modulepath = $confdir/environments/$environment/modules:$confdir/modules, for example), the agent’s environment will be interpolated into them.
  • Depending on how auth.conf is configured, different requests might be allowed or denied. The agent’s environment will also be accessible in Puppet manifests as the top-scope $environment variable.

In short: modules and manifests can already do different things for different nodes, but environments let the master tweak its own configuration on the fly, and offer a way to completely swap out the set of available modules for certain nodes.



Configuring Environments on Puppet Master :


To define  an environment master-side, just add [environment] block of
/etc/puppet/puppet.conf 
#Environments
[development]
     modulepath =/etc/puppet/development/modules
     manifest = /etc/puppet/development/manifest/site.pp
     manifestdir = /etc/puppet/development/manifest
     templatedir = /etc/puppet/development/templates

[testing]
     modulepath =/etc/puppet/testing/modules
     manifest = /etc/puppet/testing/manifest/site.pp
     manifestdir = /etc/puppet/testing/manifest
     templatedir = /etc/puppet/testing/templates

[production]
     modulepath =/etc/puppet/production/modules
     manifest = /etc/puppet/production/manifest/site.pp
     manifestdir = /etc/puppet/production/manifest
     templatedir = /etc/puppet/production/templates


Note : File serving only works well with environments if you’re only serving files from modules; if you’ve set up custom mount points in fileserver.conf, they won’t work in your custom environments.

For serving files for specific environment , just add [environment] block of  
 /etc/puppet/fileserver.conf
#Environments
[development]
   path /etc/puppet/development/files
   allow *

[testing]
   path /etc/puppet/testing/files
   allow *

[production]
   path /etc/puppet/production/files
   allow *

 

Set Environment through Manifest

The $environment variable can be used to set environment of specific host in manifest.If no $environment variable set, then by default [production] environment sevred.

Configuring Environments on Puppet Master for specific Host through LDAP node :

Create LDAP node for holding parameter for all machines .parent.ldif contains all configuration (puppetVar) that are inherited by all host. We can see both host specific ldif contains environment variable specifing its environment.

/usr/local/etc/openldap/parent.ldif 
dn: cn=parentnode,dc=mypuppet,dc=com
objectClass: device
objectClass: puppetClient
objectClass: top
puppetVar: tomcatport=8080
cn: parentnode

Add parent directory entry : 
$ /usr/bin/ldapadd -h 192.168.145.117 -p 389 -x -D "cn=Manager, dc=mypuppet, dc=com" -w yourldappassword -f /usr/local/etc/openldap/parent.ldif


Create LDAP directory for myhost1  containing host specific environment variable. 

/usr/local/etc/openldap/myhost1.ldif 
dn: cn=myhost1,dc=mypuppet,dc=com
environment: production
objectClass: device
objectClass: puppetClient
objectClass: top
parentNode: parentnode
puppetClass: tomcat
puppetVar: tomcatport=9000
cn: myhost1

Add Ldap  directory entry for host myhost1:

$  /usr/bin/ldapadd -h 192.168.145.117 -p 389 -x -D "cn=Manager,dc=mypuppet,dc=com" -w yourldappassword -f /usr/local/etc/openldap/myhost1.ldif


Create LDAP directory for myhost2  containing host specific environment variable.

/usr/local/etc/openldap/myhost2.ldif 
dn: cn=myhost2,dc=mypuppet,dc=com
environment: development
objectClass: device
objectClass: puppetClient
objectClass: top
parentNode: parentnode
puppetClass: tomcat
puppetVar: tomcatport=8000
cn: myhost2

Add directory entry for host myhost2
$  /usr/bin/ldapadd -h 192.168.145.117 -p 389 -x -D "cn=Manager,dc=mypuppet,dc=com" -w yourldappassword -f /usr/local/etc/openldap/myhost2.ldif


Configuring Environments on Puppet Client :

To set an environment agent-side, just specify the environment setting in either the[puppetd] or [main] block of  /etc/puppet/puppet.conf 

[puppetd]
  environment = development

As with any config setting, you can also use a command line option: 

$  sudo /usr/sbin/puppetd --environment development


References :
http://docs.puppetlabs.com/guides/environment.html

Monday, January 7, 2013

Installing and Configuring Puppet with LDAP Server


Blog describing my own experience of the Puppet installation procedure on RHEL5 or CentOS 5.
Note: 
  • Content procedure had been developed and tested only on CentOS 5.5, therefore it may be completely unsuitable for other operating systems including RHEL5.
  • 192.168.145.117 is Puppetmaster box IP , do replace with your puppetmaster IP.

Puppet Master Setup
[+] Installation Puppet Master

Run the following commands
$  sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
$  sudo yum install puppet-server
$  sudo yum install ruby-ldap

(Optional) If you want “—help” commands to show useful stuff install the “ruby-rdoc” package

$  sudo yum install ruby-rdoc

[+] Configuring Puppet Master 
Edit following puppet configuration file from default.

/etc/puppet/puppet.conf
[main]
    # The Puppet log directory.The default value is '$vardir/log'.
    logdir = /var/log/puppet

    # Where Puppet PID files are kept.The default value is '$vardir/run'.
    rundir = /var/run/puppet

    # Where SSL certificates are kept.The default value is '$confdir/ssl'.
    ssldir = $vardir/ssl

    #LDAP server configuration
    node_terminus=ldap
    ldapserver = 192.168.145.117
    ldapport = 389
    ldapbase = dc=mypuppet,dc=com
    ldapuser = cn=Manager,dc=mypuppet,dc=com
    ldappassword = yourldappassword
    ldapclassattrs = puppetclass
 
    factpath = $vardir/lib/facter

[puppetd]
    # The file in which puppetd stores a list of the classes associated with the retrieved configuratiion.  
    # Can be loaded in the separate ``puppet`` executable using ``--loadclasses``.
    # The default value is '$confdir/classes.txt'.

    classfile = $vardir/classes.txt

    # Where puppetd caches the local configuration.  An extension indicating the cache format is   
    #added automatically.The default value is '$confdir/localconfig'.

    localconfig = $vardir/localconfig
    ignorecache = true
    runinterval = 500000

[puppetmasterd]
   certname=puppet
   node_terminus=ldap
   ldapserver = 192.168.145.117
   ldapport = 389
   ldapbase = dc=mypuppet,dc=com
   ldapuser = cn=Manager,dc=mypuppet,dc=com
   ldappassword = yourldappassword
   ldapclassattrs = puppetclass

   ignorecache = true
   modulepath =/etc/puppet/modules

/etc/puppet/namespaceauth.conf
[fileserver]
    allow *
[puppetmaster]
    allow *
[puppetrunner]
    allow *


LDAP  Server  ( configuration store for Puppet) Setup

[+] Installating Ldap Server

for installation use following links::

[+] Configurating Ldap Server

edit from default configuration in LDAP configuration file :

/usr/local/etc/openldap/slapd.conf
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
include        /usr/local/etc/openldap/schema/core.schema
include        /usr/local/etc/openldap/schema/cosine.schema
include        /usr/local/etc/openldap/schema/inetorgperson.schema
include        /usr/local/etc/openldap/schema/nis.schema

# Allow LDAPv2 client connections.  This is NOT the default.
allow bind_v2
disallow bind_anon 
require authc

# ldbm and/or bdb database definitions

database      bdb
suffix        "dc=mypuppet,dc=com"
rootdn        "cn=Manager,dc=mypuppet,dc=com"

# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.

rootpw        yourldappassword

# The database directory MUST exist prior to running slapd AND 
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory    /var/lib/ldap

# Indices to maintain for this database
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub



Add puppet.schema file to the location /usr/local/etc/openldap/schema/

you can puppet.schema from URL:
https://github.com/puppetlabs/puppet/blob/master/ext/ldap/puppet.schema 

/usr/local/etc/openldap/schema/puppet.schema
attributetype (  1.3.6.1.4.1.34380.1.1.3.10 NAME 'puppetClass'
        DESC 'Puppet Node Class'
        EQUALITY caseIgnoreIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.34380.1.1.3.9 NAME 'parentNode'
        DESC 'Puppet Parent Node'
        EQUALITY caseIgnoreIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
        SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.34380.1.1.3.11 NAME 'environment'
        DESC 'Puppet Node Environment'
        EQUALITY caseIgnoreIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.34380.1.1.3.12 NAME 'puppetVar'
        DESC 'A variable setting for puppet'
        EQUALITY caseIgnoreIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

objectclass ( 1.3.6.1.4.1.34380.1.1.1.2 NAME 'puppetClient' SUP top AUXILIARY
        DESC 'Puppet Client objectclass'
        MAY ( puppetclass $ parentnode $ environment $ puppetvar ))

Edit LDAP Server configuration file for including puppet.schema in/usr/local/etc/openldap/slapd.conf
include              /usr/local/etc/openldap/schema/puppet.schema

Start LDAP Server
$  sudo /etc/init.d/ldap start
or
$ sudo /etc/openldap-2.4.20/servers/slapd/slapd -h ldap://192.168.145.117:389/

/usr/local/etc/openldap/default.ldif
#root node
dn: dc=mypuppet,dc=com
dc: mypuppet
objectClass: dcObject
objectClass: organizationalUnit
ou: Apes Incorporated

add root directory entry :
$ /usr/bin/ldapadd -h 192.168.145.117 -p 389 -x -D "cn=Manager, dc=mypuppet, dc=com" -w yourldappassword -f /usr/local/etc/openldap/default.ldif

Create LDAP directory for myhost1 /usr/local/etc/openldap/myhost1.ldif
dn: cn=myhost1,dc=mypuppet,dc=com
objectClass: device
objectClass: puppetClient
objectClass: top
puppetClass: tomcat
puppetVar: tomcatport=9000
cn: myhost1

add directory entry for host myhost1:
$  /usr/bin/ldapadd -h 192.168.145.117 -p 389 -x -D "cn=Manager, dc=mypuppet, dc=com" -w yourldappassword -f /usr/local/etc/openldap/myhost1.ldif

Open port 8140 for puppet master
sudo /etc/iptables -I INPUT 1 -p tcp  --dport 8140 -j ACCEPT 
sudo /etc/init.d/iptables save
sudo /etc/init.d/iptables restart

add entry for puppet master and puppet client in /etc/hosts
192.168.145.117    puppet
myhost1_ip       myhost1.puppet.com

Puppet Client Setup

[+] Installation Puppet Client 

Run the following commands
$ sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
$ sudo yum install puppet

(Optional) If you want “—help” commands to show useful stuff install the “ruby-rdoc” package

$ sudo yum install ruby-rdoc

Open port 8139 for puppet client
$ sudo /etc/iptables -I INPUT 1 -p tcp  --dport 8139 -j ACCEPT 
$ sudo /etc/init.d/iptables save
$ sudo /etc/init.d/iptables restart

Add the following configurations to /etc/hosts, for direct communication between puppet client and puppet master.
192.168.145.117    puppet

[+] Configuring Puppet Client  

/etc/puppet/puppet.conf
[main]
    # The Puppet log directory.The default value is '$vardir/log'.
    logdir = /var/log/puppet

    # Where Puppet PID files are kept.The default value is '$vardir/run'.
    rundir = /var/run/puppet

    # Where SSL certificates are kept.The default value is '$confdir/ssl'.
    ssldir = $vardir/ssl

[puppetd]

    # The file in which puppetd stores a list of the classes associated with the retrieved configuratiion.  Can be loaded in the separate ``puppet`` executable using the ``--loadclasses`` option.The default value is '$confdir/classes.txt'.
    classfile = $vardir/classes.txt

    # Where puppetd caches the local configuration.  An extension indicating the cache format is 
    #added automatically.The default value is '$confdir/localconfig'.
    localconfig = $vardir/localconfig

   #Custom configuration
   listen = true
   runinterval = 30000
   ignorecache = true



/etc/puppet/namespaceauth.conf
[fileserver]
    allow *
[puppetmaster]
    allow *
[puppetrunner]
    allow *

[+] Running Puppet Master 

Run the following command Enable server startup on boot
$ sudo /sbin/chkconfig puppetmaster on

start puppet master
$ sudo /etc/init.d/puppetmaster start

alternative commands to start/stop/restart/status PuppetMaster
$ sudo /etc/init.d/puppetmaster start|stop|restart|status


Puppet Client-Master Communication Authentication :

[+ ] Generate SSL certificate request 

On puppet client machine ,Run the following command to generate request :
$ sudo /usr/sbin/puppetd –-test --debug

[+ ]Check and Sign SSL certificate request  

Check the pending requests at Puppet master Machine using following command :
$ sudo /usr/sbin/puppetca –-list

The above command should return the machine name (in lower case) as shown below. (by default certificate name is host name of box, we can change /etc/puppet/puppet.conf) :
“puppet_client_machine_name”

Sign the SSL certificate using the following command :
$ sudo /usr/sbin/puppetca –-sign “puppet_client_machine_name”

Command to pull latest configurations from puppetmaster
$ sudo /usr/sbin/puppetd --test  --debug

[+] Running Puppet Client 

commands to start/stop/restart/status Puppet
$ sudo /etc/init.d/puppet start|stop|restart|status

Command to pull latest configurations from puppetmaster
$ sudo /usr/sbin/puppetd --test  --debug

Fire puppet client in listen mode for push based configuration support :
$ sudo /usr/sbin/puppetd --listen --no-client