Breaking an Existing Playbook into a Role
Start course
1h 27m

Sprawling infrastructure and snowflake woes? Then Ansible is the solution you need!

Ansible is designed to be minimal in nature, consistent, secure and highly reliable! Ansible is a highly sought after skill in the marketplace with an extremely low learning curve for administrators, developers and IT managers.

The "Ansible Essentials: Simplicity in Automation Technical Overview" course introduces you to Ansible automation and configuration management, provisioning, deploying, and managing compute infrastructure across cloud, virtual, and physical environments.

By taking this course you'll learn just how easy it is to use Ansible to build consistent and repeatable infrastructure environments using Ansible playbooks.


In this video, we are going to discuss how to break the existing playbook that we created in our introduction to playbook video into our existing role structure. So I am back in my text editor of choice and I am on my site.yml file and as you can see I have got all my tasks listed in here already. So what I want to do now is take these tasks and move them into their respective roles. So in the previous video, I created two roles, the apache, and the common roles, and so now I am actually going to move these pieces out.

So I am first going to start with the common role, and I am actually going to do something a little different here. So if I expand this on the left-hand side, you can see I have got the full structure underneath and if I go into my tasks file I have got, the main.yml, it’s empty, ready for my tasks. However, what I am actually going to do is I am going to build upon this common role a little bit, because right now I just have a couple of tasks, nothing crazy, but I want to show some different ways that you can utilize this role structure.

So what I am actually going to do is I am going to create a couple of additional files to place inside of my task directory for the common role. So I am first going up here and I am going to create two new files and I’m going to name them selinux.yml, so that’s one. Second, I am going to name this one ntp.yml and so now as you can see on the left-hand side here, I have three files underneath the tasks directory.

So I’ve got my main.yml, selinux.yml and ntp.yml, so this is where I am going to kind of expand upon the role. So if I go back to my site.yml, I have two SELinux related tasks, and so it would make sense for me to actually copy and paste these over to that file. So I'm going to cut those and put my three dashes (---) in to start the YAML file and then I am just going to fix the syntax, make sure that it’s all over and all that good stuff.

Basically notice that I don’t have the tasks header at the top of this file. All it is the two tasks that I have pulled over from site.yml. So now I have my two SELinux tasks in here; those make sense, they’re self-contained, I am just going to save this file because now I am done. So now I am going to move on to my ntp.yml. And so again this is -- I haven’t done anything for ntp yet, so I am just building upon the common role. 

So now I am going to name my task and the first one is going to do is install ntp and I am going to use the yum module; name=ntp, state=present, and then I am going to have another task to configure the ntp file, and for that I am going to use the template module and I’m going to set the src=ntp.conf.j2 and I am going to set the destination directory dest=/etc/ntp.conf.

Now just like I mentioned before in our demonstration on handlers, I am pushing out a configuration file, I probably want to restart services so I am going to include a notify in here to restart ntp and now that I have done that I am going to actually start the service. So start ntp using the service module set the name=ntpd and set the state=started. So there are a couple of things going on with this file. I have three tasks but I need to include a handler and I also need to make sure that my template file is located inside of the templates directory.

So I am going to save this and then I am going to move on to-- I’ll start with the handler and -- just get rid of the comment, name: restart ntp, make sure that that name is what you named your notify as, otherwise it will not be able to pick it up, and then again I am just using that service module, setting the state to restarted.

So that’s all set. To finish this out I just need to go to the templates directory, make a new file, which needs to match this same name that you specified in the task, so ntp.conf.j2, and I actually have the file over here, so rather than having to write it all out.

And basically what this is, this is just a standard drift file to store the frequency offset between the system clock and the frequency required to remain in synchronization with UTC time, so that’s pretty much it. And I am just going to save this file here. I have to edit that out.

So saving that file there, and one thing I did want to point out before I move into my main.yml file is the fact that ntp server is set to a variable so that’s one of the benefits of using the Jinja template is that I can set variables inside of my template to allow for an additional layer of abstraction, and I actually have ntpserver defined up in my group_vars under all, so there is ntpserver defined as

So go back to my ntp file, I handled the template file, it’s in template directory, I put my handler inside of the handlers directory, so this file is complete and the only thing left is my main.yml file for the task directory and that’s going to be easy. Basically what I am going to do there is I am going to take the EPEL task because it doesn't really fit into either the SELinux or ntp stuff and I am going to put it at the top level here -- make sure that that’s good, and then I am going to include the other two files so it’s just an include -- actually I’ll do the SELinux first and then I will do an include of the ntp.yml file. And if I save that then the common role is now complete.

Now I can move on to the Apache role. So again same thing I am going to start with the task directory, and I am going to take the two Apache tasks that I already wrote out and I am going to put them inside of the main.yml file for the Apache role, but I am actually going to again expand upon this role a little bit by adding some additional tasks.

So the Apache role right now, all it’s doing is it’s installing and starting Apache, and I want to do a couple more things to it, so I am going to include some additional tasks. So the first thing I am going to do, install Apache, and now going to create the sites directory. And so this is where I am really going to bring in those variables that I mentioned before.

So creating the sites directory I am going to include the file module here and I am going to set the path to a variable; path={{item}}, I am going to set the state to directory, and then I am going to do a with_items and include a variable here “{{apache_dirs}}” and close that out. And we’ll get to where these are defined in a little bit. So that’s my first additional task.

Ok, so the next task I am going to add is I am actually going to copy an index.html file, and I am going to do that with the template module, so index.html.j2 which again I have to create, and then I am actually going to set the destination to a partial variable, in this case, so the destination {{apache_docroot}} and then put index.html at the end. So I will handle that template in a minute.

But I am going to move on to the next task, which is actually to copy the Apache configuration, and again I am going to do that with the template module. So source set to httpd.conf- bring in another variable – {{ansible_os_family}} and then put the j2 extension at the end.

Now what this allows me to do, is it allows me to target next inventories, I can do this with RHEL machines and I can do it with Debian machines, so it allows me to have multiple types of hosts in my inventory at the same time and I really don’t have to modify my playbook very much, which is great, saves me time. And I am also going to set my destination to a directory variable in this case, so I will go dest={{apache_config}} and now I will include the notify. So I will do the notify here to restart apache, and then I have my task to start and enable the apache service, which is actually all I need here in this tasks file.

Ok so I have my tasks files complete. Now I have to put both of my template files inside of the templates directory. So I am going to go up to the templates directory and I am going to create a couple of new files. And the first one I am going to save is the index.html.j2 file and then I am going to create another new file and save it as the httpd.conf-redhat.j2, because these are centralized machines so they are part of the Red Hat OS family, so I am going to save that and so now I have my two template files over here, so now I am just going to grab them so I can copy paste.

So here is my index.html and again we are going to talk about the different variables that are defined in here in just a second, then I am go into my httpd.conf-redhat, and again I have that template file over here. Ok, many lines. There we go. Ok. And I have now saved that file.

Now if I go back to my main.yml file you can see I do have a notify in here, so I need to make sure I include that inside of that handlers directory, so I will go and handle that, and just do name restart apache, using the service module, perfect. And so if I go back to my main.yml file, I now have completed apache role.

Now where did I define all of these variables, because I have many variables inside of both my template files as well as in my tasks file, so if I were to run this, and I hadn’t had them defined I would get an error.

So I am going to go up and go to my group_vars webservers and all of my variables are defined inside, so I have got my apache_test_message, the max_keep_alive_requests, docroot, the config directory, sites_available, sites_enabled, and if I go back down over here, you can see there’s the “{{apache dirs}}”, {{apache_docroot}}, {{ansible_os_family}}, and then if I scroll over here the {{apache_config}} and then inside of my index file there’s the apache_test_message, distribution, hostname, etc. So these are all defined and ready to go.

So that actually concludes our discussion on how to break an existing playbook into a role. Join us in our next video where we are going to discuss how to create a new role on top of our existing role structure.


About the Author
Learning Paths

Jeremy is a Content Lead Architect and DevOps SME here at Cloud Academy where he specializes in developing DevOps technical training documentation.

He has a strong background in software engineering, and has been coding with various languages, frameworks, and systems for the past 25+ years. In recent times, Jeremy has been focused on DevOps, Cloud (AWS, Azure, GCP), Security, Kubernetes, and Machine Learning.

Jeremy holds professional certifications for AWS, Azure, GCP, Terraform, Kubernetes (CKA, CKAD, CKS).