Ansible Playbooks

In this lesson we’re going to be talking about Ansible playbooks.

Now, I’ve mentioned playbooks a handful of times before this particular lesson, and here we’re going to be talking about what playbooks actually look like, how they’re structured and what information is needed to be able to run a playbook. See, playbooks are really the building blocks of Ansible network automation. You construct a playbook and execute it against your managed nodes to be able to accomplish some task in a more automated fashion, and be able to audit the completion of that task and retry it in the event it fails on some of your managed nodes.

So let’s go ahead and take a look at the structure of a playbook.

Structure of an Ansible Playbook

First up, a playbook is used to execute a series of plays. You have this structure above, where you have a playbook which is your overall file, it’s coded in YAML, we had talked about YAML in our previous data serialization lesson, and this YAML file has a collection of plays.

You can have different plays, each one of these will have a different name and a different set of tasks within each of those plays. A play runs tasks on a host or a collection of hosts, and a task calls a function defined in Ansible modules and those modules are coded in Python.

Each play consists of one or more tasks, and each task executes modules. This is just getting a little bit of what Ansible terminology is. A module is executed by a task, and a task is run within a play, and a playbook contains one or more plays, and the playbook as a whole is written in YAML.

Great! so that’s a playbook. Let’s start taking a look at the actual structure here to give a little more real-world content to our information in theory.

Initial play information for a play that will execute on a Juniper device

This illustrates the initial play information for a Juniper device specifically. Here we have a list item directly after our 3 dashes.

A play is a list item, as defined by our hyphen. Now within our list item play, here we have the name of our play, we have a definition of what hosts that this play will execute against. Then we have our list of roles that should be imported with this play. You can have one or more roles imported within a play. Then we have our connection being local, this is required due to our devices being managed via NETCONF. We should specify not to gather facts of our local ansible management host, because we just don’t need to gather facts of our Linux server every time that we execute a play.

Right, so this is just the initial little metadata information that you would have within your play, so let’s take a look at a full playbook here:

Example full playbook for gathering and printing device facts on a Juniper device

We have again our start of our YAML file with 3 dashes, and our list item which is one play, we see we have one play within this playbook here because we have one list item.

The play is called “Get Facts”, we are executing it against our vsrx group, or vsrx could potentially be the name of a host as well but here we have our group vsrx. We have our roles that we are importing, which is the Ansible Galaxy Juniper.junos role, and of course our connection is local and we are saying no for gathering facts of our local device.

Next we have our section of vars_prompt. This is a special section of the play where we can prompt the user to manually enter some variables. In this case we’re storing our username variable and our password variable, our private specification here defines whether our input that we’re typing on the keyboard is displayed on the screen while we’re typing it. Since we’re saying ‘yes’, our password should be private and we are prompting our end user for device username and device password. You could prompt for any other variables here as well!

Then we have our list of tasks. The tasks is a mapping that contains several list items. So within our list item here we have the name of our task and then we have our module that we are looking to execute. In this case the juniper_junos_facts module from the juniper.junos roll is used to gather the device information. It takes in a username and password parameter for authentication to the device, and here we are using our username and password variables.

Note that the {{ USERNAME }} and {{ PASSWORD }} is within our double braces, indicating this is Jinja formatting and our variables are replaced here using Jinja on the backend.

Finally in this particular task, we are registering the output to a variable named device_facts. The register item there is used to save the output of a module to a variable for usage later in the playbook. As we see just below that in our second task, our task is to print the device facts. The debug module is a really handy one for outputting information to the console, and here we are just outputting the entirety of the registered variable, which is device_facts.

I would go ahead and take a screenshot of this example and make sure that you are familiar with the structure of a playbook. It will likely come up within your exam, to define where certain information is. Perhaps in a drag-and-drop format or in a multiple choice.

So let’s go ahead and take a look at what it looks like to execute a playbook.

Example output when executing the example playbook seen above

We see up here on our first line that we are executing our Ansible playbook command against the junos_facts YAML file which is our playbook we have. It is prompting for both our device username and device password and our password is kept secret, it is not displayed on the screen while we’re typing it.

Our playbook is being executed against two different devices within our vsrx group. You may have seen that in our previous lesson that in the inventory our vsrx group did contain two different devices.

That task of retrieving the device facts it executed and came back with OK, it executes successfully on both of those devices. Then we are printing those facts and we see here is done in text format. We have each of our items for our facts, so we have our routing engine information, the model that this is a vsrx that this is executing against so it is the firefly model of the vsrx. The python interpreter is python 3 and that our up time here is just a little over two weeks.

Our recap of our play execution we see both of our tasks executed successfully and gave us a return of OK and then it spat us back out to the prompt here. great so that’s a overview of the structure of a playbook, for a full video lesson, please check out this lesson’s video below!

Only subscribers can view the full content. Join Now!

Scroll to top

You have successfully subscribed to the newsletter

There was an error while trying to send your request. Please try again.

CiscoLessons will use the information you provide on this form to send occasional (less than 1/wk) updates and marketing.