Puppet on command line
Now it is the right time to start the real Puppet work:
- Select the virtual machine from the list, and click on the Start button at the top of the window.
- Once the virtual machine has booted up, you should see a login prompt:
- At the login prompt, type in the user name
root
and hit Enter. Then, type in passwordpuppet
and hit Enter again. - You have now entered the development environment, where we can start familiarizing with the Puppet commands and manage our system. You are free to play around and change the configuration as much as you like.
- If you happen to break the environment, you can easily restore the original configuration from the snapshot as we did in the earlier paragraph.
Puppet version
The Puppet executable can be run from the command line. Let's begin with confirming which version of Puppet we are running. We can check the version by running the following command:
puppet --version
At the time of writing, the command run on the Learning VM, it shows the Version as 3.7.3 (Puppet Enterprise 3.7.1.).
The first Version number 3.7.3 is for the open source version of Puppet that we are using. The second Version number 3.7.1 is for the Puppet Enterprise version number.
What is the difference between these two versions? The difference between them is how these products are packaged, distributed, and supported.
The open source Puppet
The open source Puppet is the community-driven version of Puppet that is developed by the open source community and maintained by Puppet Labs. It can be used and distributed freely.
The Puppet Enterprise edition
The Puppet Enterprise edition is a distribution that is developed, maintained, and supported by Puppet Labs, which is the commercial arm behind Puppet.
Companies can purchase the Puppet Enterprise license from Puppet Labs, and in return, Puppet Labs provides support services and software updates for the Puppet Enterprise software bundle that enables companies to get up and running with Puppet quickly.
The Puppet Enterprise edition is free to use in environments that consist of 10 or less Puppet managed hosts.
The environment that we will be building throughout the course of this book will consist of four hosts only, which makes Puppet Enterprise a perfect fit for our goal of learning Puppet.
Puppet resources
So now we know how to extract the version using the Puppet command-line utility. Let's shift our focus to the resources next.
Resources in Puppet are known as types. Types are operating system resources such as a file, a user, or a package. There are tens of built-in types in Puppet, and in addition to these, you can create your own custom types to manage resources.
We will learn more about custom types later in Chapter 5, Load Balancing the Cluster, but for now we will take a look at the built-in types and see how to use them.
A complete list of available built-in types is available on the Puppet Labs website at http://docs.puppetlabs.com/references/latest/type.html.
Run the puppet describe --list
command in the Learning VM to list all the built-in types known to Puppet.
The output will contain about 60 resources and their descriptions. To paginate the output, you can extend the command by adding | less
to the end of it.
Here is the command to view the output page by page:
puppet describe --list | less
You should now be able to scroll the output up and down using the arrow keys, and you can exit the view by pressing Q on the keyboard.
All the Puppet types have attributes that are used to describe the characteristics of the resources we want Puppet to manage.
For example, the type user has attributes such as a name for the user name and a password for the user account password.
To list the available attributes for a specific type of resource, you can use the puppet describe <type>
command. For example, to list the available attributes of a type user, you can run the puppet describe user
, or puppet describe user | less
command to paginate the output.
If you scroll down the list of attributes, you can find a password attribute that is used to set a password for the user account. Another attribute that you can find on the list is called ensure
, which defines the state of the user account. The attribute can have three values:
present
: This ensures that an account is created unless it already existsabsent
: This ensures that the account is removed if it existsrole
: This is a specific user attribute of the Unix operating system, such as Oracle Solaris, and therefore it has has no meaning when running Puppet on Linux like we are doing
Managing resources from the command line
We can manage Puppet resources from the command line using the following syntax: puppet resource <type> <name> <attribute1>=<value> <attribute2>=<value>
.
Let's create a user called Elisa
on the system using Puppet. In the Learning VM terminal, type in the following command and and hit the Enter key:
puppet resource user Elisa ensure=present
When the command is executed successfully, it produces the following output:
The first line of the output displays a notice confirming that the user account Elisa
was created by Puppet. Lines 2-4 show the syntax that we will be using when we declare resources in the Puppet manifest files. The manifest files will be explained more in detail later.
Let's take a look at the syntax line by line:
- Line 1:
Notice: /User[Elisa]/ensure: created
This displays a confirmation of an action that Puppet has created a user called
Elisa
. - Line 2:
user { 'Elisa':
This declares a resource for a type user, which follows the opening curly brace (
{
), that indicates that the user resource name and optional attributes are to follow. The name'Elisa':
at the end of the line sets the Puppet resource name, which will become the name of the user account. The Puppet resource name must contain a colon at the end. - Line 3:
ensure => 'present'
This attribute means that a user account must be created unless it already exists.
- Line 4:
}
The closing curly brace indicates the end of the resource statement.
The name Elisa
on line 2 has two use cases. Firstly, it declares the name of the Puppet resource. Each Puppet resource must have a unique name, otherwise Puppet reports an error.
Secondly, the name Elisa
is used as the name of the user account that was created. If the user statement contains a name attribute (alongside the ensure attribute), then the value of the name attribute would become the name of the user account and the name Elisa
would only be used as the Puppet resource name.
As the name attribute is omitted, Puppet will use the name for the Puppet resource name as well as for the user account name.
Declaring the following statement in the Puppet manifest would result in the Jakob
user account being created in the system, as the name attribute would take priority over the Puppet resource name Elisa
:
user { 'Elisa': ensure => 'present', name => 'Jakob', }
This produces an output that is similar to the following, although the numeric information in the output may vary between the systems:
uid=501(Elisa) gid=501(Elisa) groups=501(Elisa)
Next, we can remove the account Elisa
from the system by setting the ensure
attribute value to absent
.
puppet resource user Elisa ensure=absent
Assuming that the command executes successfully, you should see the following output:
This output is very similar to how we created the user account Elisa
except that line 1 confirms that the user account Elisa
was removed and line 3 has the ensure
attribute value set to absent
, which results in the account being removed when declaring a resource in the Puppet manifest file.
To confirm whether Puppet really removed the account, you can run the command id Elisa
again, which will confirm that the account no longer exists in the system.
The command id Elisa
should produce the following output:
id: Elisa: No such user
Congratulations! You just did two system configuration changes using Puppet. It wasn't hard, right?
Puppet dry run
Sometimes, you want to simulate configuration changes without applying the changes to the system. This can be done by adding the --noop
parameter after the resource keyword in the Puppet command.
To simulate account creation without creating the account, we can extend the previous user account creation command with the --noop
option:
puppet resource user Elisa ensure=present --noop
Line1 in the output tells us that the user account does not exist in the system, and if you run the following command without the --noop
option, Puppet would create an account:
Notice: /User[Elisa]/ensure: current_value absent, should be present (noop) user { 'Elisa': ensure => 'absent', }
The --noop
option comes in handy when testing Puppet commands for a syntax. To demonstrate this, we declare an invalid value removed
for the attribute ensure
:
puppet resource user Elisa ensure=removed --noop
Puppet will return an error that tells you that we have used an invalid value for the ensure
attribute:
Use Puppet to examine the current state of resources
Puppet can also be used to query resources from the system. Information produced by the query can be helpful when we are uncertain about what syntax we should be using to create a resource.
Earlier, we created a user account called Elisa
. This account was created without a password, which means that the account cannot be used for interactive logins. Let's recreate the user account and use the password
attribute to set a password for the account.
As passwords on Linux are encrypted, we must provide them to the password
attribute in the encrypted format.
We know that the user account root on the Learning VM uses the password puppet
, but we yet don't know how the password would look like in the encrypted format.
No problem, as we can query the password with the command and then use the encrypted password when recreating the user account Elisa
.
The following command shows all the attributes for the root
user account:
Puppet resource user root
The preceding command produces the following output:
Now we can create the user account Elisa
with the password
attribute, which is the same as the value of the password
attribute for the user root
.
The following command will create the user account Elisa
that uses the password puppet
:
puppet resource user Elisa ensure=present \ managehome=true \ password='$1$jrm5tnjw$h8JJ9mCZLmJvIxvDLjw1M/'
I've split the command into three lines with the backslash character at the end of the first two lines.
Note
The $1$jrm5tnjw$h8JJ9mCZLmJvIxvDLjw1M/
string is a hash of the password puppet
. Please note that we have to use single quotes around the password hash '$1$jrm5tnjw$h8JJ9mCZLmJvIxvDLjw1M/'
because the string contains characters that the Linux command line otherwise interprets as a control character.
Now we can test whether we can log on to the system as the user Elisa
.
Log out from the system using the logout
command. Then, log in with the username Elisa
and password puppet
. You will see the following welcome screen, which confirms that the login of Elisa
was successful:
Puppet is run as a user root
The root account in Linux is equivalent to an administrator account in the Windows operating system. This is the user account that is commonly used for system configuration changes.
The user account Elisa
that we created does not have the same amount of privileges as the root account.
To change the system configuration in the protected areas of the operating system, we must run Puppet as a root user.
If you are still logged onto the system as user Elisa
, you can try creating a user account and see what happens.
As the user Elisa
is not configured to run Puppet, we will do our test using the Linux adduser
command.
Let's see what response we get if we try to create a user called Jakob
using the user Elisa
:
useradd Jakob
The output of the preceding command shows you that the user Elisa
did not have sufficient permissions to add a new user to the system:
/usr/sbin/useradd: Permission denied
To avoid possible permission issues on Puppet managed systems, Puppet runs as a user root that provides Puppet full control of the system to add and remove users, install and uninstall software packages, as well as manage system services.
In the end, Puppet is your new system administrator, which manages the system according to the instructions you have provided from the command line or in the form of the Puppet manifest.
Puppet DSL and manifests
I've mentioned Puppet manifests earlier, but I haven't yet explained what manifests are. Puppet manifests are text files that declare one or more Puppet resources. Instead of running Puppet resource commands on the command line, you can declare resources in the manifest file and apply the manifest to the system.
Puppet manifests uses the Puppet Domain Specific Language (DSL) and resource statements in the manifest file, which are described in a syntax that looks very similar to a Hash data type in the Ruby language.
We can use our user account Elisa
as a simple example of the Puppet manifest syntax.
First, log out from the user account Elisa
by running the logout
command. Then, log on to the system as a root user and remove the user Elisa
from the system with the following command:
puppet resource user Elisa ensure=absent
Then, inspect the state of the user account Elisa
with the following commands:
puppet resource user Elisa user { 'Elisa': ensure => 'absent', }
In the Ruby language, if we try to declare a hash called User
that contains a key Elisa
with the value of the ensure
attribute as absent
, we will declare it using the following syntax:
User = { 'Elisa' => { 'ensure' => 'absent' } }
If you compare the preceding two code blocks, you can see that the Puppet DSL syntax looks similar to the Ruby language syntax, but it is slightly simpler and easier to read than the Ruby equivalent.
The output of the preceding Puppet resource command is spread across three lines only in order to make it easier for us to read. The Puppet parser that reads the manifest file doesn't care about the line feed characters.
The preceding user resource can be declared on a single line as follows:
user { 'Elisa': ensure => 'absent', }
We now have the Puppet DSL representation of the user resource Elisa
.