In this hands-on lab, we’ll be focusing on learning and using the basic components of a Puppet module. A module in Puppet is a collection of Puppet code that helps us configure an end state — specifically, we’re going to be creating a basic module that installs, configures, and starts the MySQL service.
As we create this module, we’ll learn about manifests, classes, class definitions, resource types and definitions, and the syntax used to create simple Puppet code. Once finished, the student will have an understanding of the core components of a Puppet class, and can start exploring more advanced features, such as templating, including Hiera, and creating parameters.
Learning Objectives
Successfully complete this lab by achieving the following learning objectives:
- Create an installation class
Generate the
mysql
module:$ cd /etc/puppetlabs/code/environments/production/modules $ sudo pdk new module mysql
Name the module
mysql
and use your own information when prompted for a Puppet Forge account and module author. Note that if you do not have a Puppet Forge account, you can leave that option as-is. Leave the licensing with the default information, and set the operating system to RedHat- and Debian-based Linux. Generate the metadata.Generate the open the
install.pp
manifest:$ cd mysql $ sudo pdk new class install $ sudo vim manifests/install.pp
Review the class declaration — this provides Puppet with a unique name reference for the class we’re creating:
class mysql::install { }
Set the resource type with a resource name:
class mysql::install { package { 'mysql-server-5.7': } }
We’re using the
package
resource because we are installing and otherwise managing a package.mysql-server-5.7
is the package name, which can also be supplied in the body of the resource declaration with thename
attribute.Speaking of attributes, let’s ensure we’re actually downloading the package by supplying the
ensure
attribute. Attributes are ways of detailing the specifics of our resource. In this case, we just have to state that we want the package installed with thepresent
value:class mysql::install { package { 'mysql-server-5.7': ensure => 'present', } }
Save and exit. We can now check for syntax errors with:
$ sudo puppet parser validate manifests/install.pp
If no data is returned, then we’re structurally sound.
- Create a configuration class
Create a configuration class:
$ sudo pdk new class config $ sudo vim manifests/config.pp
Download the MySQL configuration file and add it to the
files
directory under themysql
module. This is where all static files are stored.$ sudo curl https://raw.githubusercontent.com/linuxacademy/content-ppt206-extra/master/mysql.cnf -o files/mysqld.cnf
Update the file to note it is being managed by Puppet:
$ sudo vim files/mysqld.cnf # This file is managed by Puppet #
Open the
config
manifest and set the resource type. We’re going to use thefile
resource type:$ sudo vim manifests/config.pp class mysql::config { file { '/etc/mysql/mysql.conf.d/mysqld.cnf': ensure => 'file' } }
Set the associated attributes. We specifically want to include the file mode, owner, group, and file source:
class mysql::config { file { '/etc/mysql/mysql.conf.d/mysqld.cnf': ensure => 'file', source => "puppet:///modules/mysql/mysqld.cnf", mode => '0644', owner => 'root', group => 'root', } }
Notice how
source
lets us use a Puppet URI to reference the location of the file on our master in shorthand.puppet:///
references the environment we’re in. We can also leave out thefiles
directory reference.Save and exit the file.
Check the file’s syntax with the Puppet parser:
$ sudo puppet parser validate manifests/config.pp
- Create a service class
Finally, we want to make sure the
mysqld
service is started, enabled to start at boot, and is set to restart whenever there are changes made to our config file. Let’s first create the manifest and define our resource type:$ sudo pdk new class service $ sudo vim manifests/service.pp class mysql::service { service { 'mysql': } }
Next, we want to supply our attributes. The
ensure
andenable
attributes are fairly self-explanatory:class mysql::service { service { 'mysql': ensure => 'running', enable => 'true', } }
However, we also want to assign it the
hasrestart
parameter, which will allow for restarts under certain circumstances:class mysql::service { service { 'mysql': ensure => 'running', enable => true, hasrestart => true, } }
Save and exit the file.
Run the Puppet parser against the
service.pp
manifest:$ sudo puppet parser validate manifests/service.pp
We’re not quite done, however. We want to reopen the
config
class to ensure it triggers theservice
class to restart. To do this, we use thenotify
metaparameter, assigning it to the resource in ourservice
class:class mysql::config { file { '/etc/mysql/mysql.conf.d/mysqld.cnf': ensure => 'file', source => 'puppet:///modules/mysql/mysqld.cnf', mode => '0644', owner => 'root', group => 'root', notify => Service['mysql'] } }
Save and exit.
We now need to tie our module together with an
init.pp
class. Generate the class:$ sudo pdk new class mysql
Then use the class as a wrapper to contain our other classes:
$ sudo vim manifests/init.pp class mysql { include mysql::install include mysql::config include mysql::service }
- Test the module
Log in to the Ubuntu node and bootstrap it to use Puppet:
$ curl -k https://puppet.ec2.internal:8140/packages/current/install.bash | sudo bash
Approve the node on the master:
$ sudo puppetserver ca sign --all
We now need to map our
mysql
module to ournode1
node. First, let’s open up the main manifest — or where we perform all these mappings:$ sudo vim /etc/puppetlabs/code/environments/production/manifests/site.pp
Next, let’s add a node definition and assign our module:
node node1.ec2.internal { include mysql }
Save and exit.
Return to the
node1
node and test the module:$ sudo puppet agent -t