7 minutes
AAP and Infrastructure as Code
Picture this. You’re tasked with creating a brand new instance of Ansible Automation Platform your team to match the current production instance. Easy right? Red Hat makes this process easy with an intiutive Ansible playbook and structured inventory file to make the installation process relatively painless.
But what happens once the instance is complete? By now, your team most likely has tens, if not hundreds of job templates, projects, inventories, credentials; all of these resources that must now be re-created manually. Unless you really enjoy clicking the same button hundreds of times, this manual process is both inefficient, boring, and prone to user error.
Enter Ansible and “Infrastructure as Code”. You may have heard the term thrown around as your boss’ new favorite lingo, but what is it actually? Simply put, its a process where we use code to provision infrastructure and its underyling resources, instead of doing everything manually, and Ansible is a great tool to use in this regard.
Red Hat provides a certified Ansible collection, ansible.controller that we can use to easily create resources inside of Ansible Automation Platform. In the below tutorial, I’ll go over a few examples of how to create job templates, credentials, and inventories using Ansible and this collection.
Prerequisites
The ansible.controller collection requires a few pieces of information to be provided in order for it to successfully run tasks. This information can be provided either through parameters passed to the module, environment variables, or a config file. I’ve provided an example config file below for reference:
[general]
host = https://localhost:8043
verify_ssl = true
oauth_token = LEdCpKVKc4znzffcpQL5vLG8oyeku6
You can then pass the location of the config file as a parameter to the Ansible module:
- name: Add Something
inventory:
...
controller_config_file: "~/tower_cli.cfg"
Authentication
Authentication can be accomplished using two methods:
- OAuth2 Token
- Username and Password
The OAuth2 token method is preferred by the collection, but either is appropriate. THis tutorial will use a bugus OAuth2 token and host in the below examples.
SSL
Unless otherwise specified in the installation, Ansible Automation Controller will install with a self-signed certificate. Your client must be able to trust the SSL certificate of the AAP controller in order to run tasks.
Another option, although less secure, is to disable certificate varification when using the Ansible module:
- name: Add Something
ansible.controller.inventory:
...
validate_certs: false
Creating Credentials
Source Control
One of the first tasks when setting up a new instance of Ansible Automation Controller is to sync your team’s set of playbooks from Git. Before you can do that, however, you must have appropriate credentials created to access said resource.
Let’s assume that I have created an SSH key pair to act as my source control credential. We’ll need the private key (the public will be stored in GitHub or GitLab), stored somewhere on our client machine. In this example, my private RSA SSH key is stored in my user’s home directory /home/someuser/.ssh/id_rsa, and this credential, named Git Credential, will be created within the Default organization.
- name: Create a Source Credential
ansible.controller.credential:
name: Git Credential
organization: Default
state: present
credential_type: Source Control
inputs:
username: "{{ git_username }}"
ssh_key_data: "{{ lookup('file', '/home/someuser/.ssh/id_rsa') }}"
With this source control credential, we can now access and sync our playbooks stored in our Source Control instance. However, this is not the only credential we’ll need to get started.
Machine Credential
In order to access our Linux hosts and run the tasks defined in our playbooks, we’ll need to define a credential we can use to access said hosts.
We will assume that on our target servers, there is a user that has the ability to gain elevated privileges using sudo. Like before, the credential will be created within the Default organization.
- name: Create a Machine Credential
ansible.controller.credential:
name: "Machine Credential {{ credential_username }}"
description: "Credential for the {{ credential_username }} account"
organization: Default
credential_type: Machine
state: present
inputs:
username: "{{ credential_username }}"
password: "{{ credential_password }}"
become_method: sudo
become_username: root
become_password: "{{ credential_password }}"
There are instances where you wish to prompt for the password of a machine credential, instead of storing it inside of AAP. You can configure this behavior like so:
- name: Create a Machine Credential
ansible.controller.credential:
name: "Service Credential"
description: "Credential for the {{ credential_username }} account"
organization: Default
credential_type: Machine
state: present
inputs:
username: "{{ credential_username }}"
password: "ASK"
become_method: sudo
become_username: root
become_password: "ASK"
With this, we’ve now successfully created the credentials needed to sync our playbooks and connect to our target machines.
Projects
With our source control credential in hand, we can now begin to sync our playbooks and other required resources from our Source Control instance.
Creating a project via Ansible is easy; using the SCM URL of our playbooks git project, plus our earlier created Source Control credential (named Git Credential), we can create our project like so:
- name: Create a Playbooks Project
ansible.controller.project:
name: "Playbooks"
description: "Playbooks Project"
organization: Default
credential: "Git Credential"
scm_type: git
scm_url: "{{ git_url }}"
scm_update_on_launch: true
You’ll notice that scm_update_on_launch is set to true in the above example. This allows AAP to automatically update its version of the Playbooks project every time a job is launched using an asset from that project. If you do not wish this behavior, simply set it to false.
Inventories
Playbooks are a critical part of Ansible, but are useless without a set of hosts to run against. Inventories provide this list.
There are two steps to creating an AAP Inventory; creating an inventory, and creating an inventory source. An inventory source is where host data is actually sourced from, such as an inventory file inside a project, VMWare, Red Hat Insights, and many others. A list of inventory plugins can be found here.
We’ll first create an inventory using the following Ansible task:
- name: Add Inventory
ansible.controller.inventory:
name: "Prod Inventory"
description: "Production Servers"
organization: "Default"
state: present
Next, we will create an inventory source for the above inventory. Each source type will have its own set of variables that need to be defined. The link provided above that lists inventory plugins also provides required variables for each plugin. For this example, I will simulate the use of VMWare as an inventory source.
- name: Add Inventory Source
ansible.controller.inventory_source:
name: "VMWare Inventory"
description: "Prod VMWare Inventory"
inventory: "Prod Inventory"
overwrite: true
update_on_launch: true
organization: Default
source_vars:
strict: false
hostname: "{{vmware_hostname}}"
username: "administrator@vsphere.local"
password: "{{vmware_password}}"
validate_certs: false
with_tags: true
Job Templates
Now that we have created our required credentials, projects, and inventories, it is finally time to create job templates so we can begin to run Ansible playbooks inside of AAP.
In the below example, I will create a job template that calls a fake playbook called website.yml located inside the Playbooks project, using the Service Credential Machine Credential, and the Prod Inventory inventory.
- name: Create Job template
job_template:
name: "Ping"
job_type: "run"
organization: "Default"
inventory: "Prod Inventory"
project: "Playbooks"
playbook: "website.yml"
credentials:
- "Service Credential"
state: "present"
One critical aspect of job templates is the use of surveys; a user friendly question-answer form that sets the values of extra variables that can be used to alter the behavior of playbooks.
Creating a survey for a job template using Ansible requires the creation of a survey config file, the file name of which is passed to the above task, like so:
survey_enabled: yes
survey_spec: "{{ lookup('file', 'survey.json') }}"
I’ve provided an example survey config file below that you can use to reference when creating your own:
{
"name": "Example Survey",
"description": "An Example Survey",
"spec": [
{
"type": "multiplechoice",
"question_name": "Production Status",
"question_description": "Production Status to Deploy To",
"variable": "prod_status",
"choices": ["nonprod","prod"],
"required": true,
"default": "nonprod"
}
]
}
More survey spec examples can be found in the Red Hat Developer Ansible Automation Platform Controller API Guide posted below.
We now have officially created everything we need to start running Automation inside of Ansible Automation platform; all using Ansible playbooks to create the resources we need. Hopefully this serves as an excellent starting point as you start to develop Infrastructure as Code workflows during your Ansible journey.
See Also
Red Hat Developer Ansible Automation Platform Controller API Guide