Ansible Tower REST API Part 1

This post is about the basics of using the Ansible Tower REST API with code from real world deployments, part two is here. At Haystack Networks, we have deployed Ansible Tower with basic front ends for customers when deploying Cisco ACI fabrics. This is intended to allow the customers to explore the basic capabilities extended through the Cisco APIC and Ansible Tower REST API’s. The basic scripts are always written to aid the customer in BAU tasks such as setting up new customers in the case of a cloud provider or just creating new vPC configurations in many cases of deployments which of course speeds up the provisioning process but also keeps the configuration consistent and prevents the use of wizards creating redundant objects polluting the APIC object model and becoming orphan objects when configurations are deleted, this can be a problem further down the line.

So we have a deployment of the following as a reference system for this post:

  • ACI fabric
  • Ubuntu LTS 16.0.4
    • Ansible
    • Ansible Tower
    • Custom HTML pages

The method for installing Ansible is the subject of a previous post which can be found here. Ansible Tower is also installed on this machine, I don’t have a post yet on installing Ansible Tower but there are many resources on the Internet that can help with this, Ansible Tower distributions can be found here.. I will go through the configuration of Ansible Tower following the basic installation in this post. The custom HTML pages are the front end pages that the user will select a task from, enter task details and submit the job to Ansible Tower to  configure the APIC.

Keep in mind that the flow of this system is linear as shown in the following image:

Ansible


Lets start with Ansible,  when we talk about Ansible we also mean the playbook that Ansible will call, this is selected in the Ansible Tower configuration which we will deal with in the next section. The Ansible playbook we will use is one in which a customer wanted a specific configuration (as always!!) and is not actually the recommended way to connect EPG’s to AEP’s, the method here is to assign the EPG to an AEP with a VLAN ID in the AEP configuration, ever wondered what that setting was at the bottom on the AEP page – well know you know. It assigns the entire EPG to a VLAN on a specific EPG, as I said not a Cisco recommended configuration as it is really there for deployments in which the end user does not want to get involved with scripting static ports in an EPG. I am using this script for this post as it uses both Cisco Ansible modules specific to a task and also the Cisco “aci-rest” module which takes raw XML as input in the playbook so a mix of both styles of configuration of the APIC in a playbook and is an instance/example of a L2 deployment.

The playbook doesn’t look that much different to a normal Ansible playbook but we need to make some changes for APIC authentication.

  vars:
    aci_login: &aci_login
      hostname: '{{ inventory_hostname }}'
      username: "{{ lookup('env', 'ANSIBLE_NET_USERNAME') }}"
      password: "{{ lookup('env', 'ANSIBLE_NET_PASSWORD') }}"
      validate_certs: no

I use a variable to hold the authentication parameters like hostname, username and password called “aci_login” which is referenced in each task. The changes that need to be made are the username and password parameters. The parameters for these variables are again variables themselves, but these are Ansible global variables set for this playbook by Ansible. We use the lookup command to get the global variables “ANSIBLE_NET_USERNAME” and “ANSIBLE_NET_PASSWORD”, this username\password pair is defined in Ansible Tower for each job template and are the credentials for the APIC.

We need to save the playbook YAML file in a different location than the usual location for when we have only Ansible running. Ansible Tower by default looks for playbooks in the directory ‘/var/lib/awx/projects/’. You can change this directory using the Tower configuration section which has a global effect. Create a sub directory within this path for organisation of different types of scripts. We will put this YAML playbook into a new sub directory called ‘haystacknetworks’. If the directory path does not exist then either create it or wait until Ansible Tower has been installed the add your own sub directory.

The Ansible playbook YAML file can be found here on Github.

Ansible Tower


Ansible Tower should be installed for this step, generally the install is straight forward with a download, decompressing the tar file, changing some variables in a playbook then running the install. You can find the installation guide here.

Once installed we can start to configure Ansible Tower for the Cisco APIC and for the playbook we created earlier. The diagram below shows the relationship between configurable components of Ansible Tower for a project.

Looking at the diagram we have a number of components to configure. The Job Template is what is used by Ansible Tower, a Job Template has an identifier which is specified by the REST API when requesting a new job to be run (playbook to be run) or when gathering the status and details of a job. In order to create a function Job Template we need to first configure other items as shown in the diagram for the Job Template to use.

Inventory

The inventory is a list of hosts for Ansible to run the playbook against, in this instance it will be the APIC controller IP. To create an inventory list, use the option “Inventories” and click Add and name the Inventory list and save. Click the Add Host button to add a host, the host name can be a DNS resolvable name or an IP address. In this configuration we use an IP address.

 

Project

We next configure a project, the project contains the SCM type, and playbook directory which we must select. The SCM type will be manual in this example but other options such as Git are available for central management of scripts. The playbook directory drop down should contain the sub directories in the root projects folder we discussed earlier. Select the relevant folder for this project that contains all the playbooks required for jobs connected to this project.

 

Credentials

There are three types of credentials that can be used in a Job Template, in this configuration we are only using two, namely – Machine and Network credentials. The cloud credential can be used by a Job Template but for the APIC this is not required. The machine credential is actually an empty one as we don’t have any machines (desktop, server, etc) to configure. We do have an APIC and the APIC requires an username/password, we need to pass the username/password to the Ansible script for the APIC. As a reminder, the Cisco Ansible modules use a REST API over HTTPS to the APIC and not the default SSH method of Ansible. The Network credential will hold our APIC username/password, bear in mind this credential must allow all possible configuration tasks in the Ansible playbook, you can restrict the use of this credential and/or playbooks called by users by implementing different users and team roles applied to jobs so to restrict what playbooks the users can call.

The credentials are in the settings menu option (the cog at the top left) and then within the tile ‘Credentials’. The following screenshot shows the configuration of an empty machine credential.

We also configure the Network credential  for the login to the APIC as follows;

Users

A Job Template uses permissions to enable users or teams to run the job and therefore the playbook. We will configure a user in this example but a better method is to assign permissions to teams (user groups) and add/remove users from the team. In Settings, then the User tile, select the Add button. This user is configured as a normal user which is a user without administrator privileges. Bear in mind, these logins allow the user to login to Ansible Tower, this is normal of course as a user has to be able to run a job they have the permissions to do so. We are providing a custom HTML page in this case but the user needs to be able to login to Tower and the GUI is just a REST API client just like our custom HTML page. We can also configure the users permissions to job templates within the user configuration once the initial user configuration is saved but we will do this via the job template once created.

Job Template

The final task is to pull all this together in a job template. We create a new job template for a playbook which creates a custom tenant on the APIC with associated configuration which is shown in the playbook file. As shown in the following screenshots we complete the template using the configuration sets we have defined in this post. Ensure the “Prompt on Launch” checkbox is selected if your playbook takes variables as input, this setting causes Tower to prompt for playbook parameters if run from within Tower and also it allows Tower to accept variables as input via the REST API, if you do not select this and use the REST API to send playbook parameters with a job request, the request will fail with no variables passed to the playbook as Tower will ignore any variables passed from the REST API input.

The following two screen shots show this configuration.

And the second screen shot further down the same screen…

After saving the Job Template,  click the Permissions button, this will allow you to add in user accounts setup earlier with permissions to run or schedule the job. Assigning a user to allow only the running or scheduling of a job without change or admin rights is done by assigning the user the “execute” permission only. This is shown with our user we created called “devops1”,  this account will allow the user to login to Ansible Tower without admin rights and run or schedule this job.

We now have Ansible & Ansible Tower setup ready for a REST API Job run request. We will go through using the REST API in the next part of this blog which you can find here.

 

2 Replies to “Ansible Tower REST API Part 1”

  1. Pingback: Ansible Tower REST API Part 2 - Haystack Networks

  2. Matt Mullen

    Many thanks for this…

    lookup(‘env’, ‘ANSIBLE_NET_USERNAME’)

    That is a gem that is pretty well hidden, and would have struggled with it longer had I not run across your post!

Comments are closed.