Variables

We discussed variables a bit in the previous section. Because our managed nodes are not exactly alike, we need to accommodate the differences via variables. Variable names should be letters, numbers, and underscores, and should always start with a letter. Variables are commonly defined in three locations:

  • The playbook
  • The inventory file
  • Separate files to be included in files and roles

Let's look at an example of defining variables in a playbook, cisco_1.yml:

---
- name: Configure SNMP Contact
hosts: "nexus"
gather_facts: false
connection: local

vars:
cli:
host: "{{ inventory_hostname }}"
username: cisco
password: cisco
transport: cli

tasks:
- name: configure snmp contact
nxos_snmp_contact:
contact: TEST_1
state: present
provider: "{{ cli }}"

register: output

- name: show output
debug:
var: output

You can see the cli variable declared under the vars section, which is being used in the task of nxos_snmp_contact.

For more information on the nxso_snmp_contact module, check out the online documentation (http://docs.ansible.com/ansible/nxos_snmp_contact_module.html).

To reference a variable, you can use the Jinja2 templating system convention of a double curly bracket. You don't need to put quotes around the curly bracket unless you are starting a value with it. I typically find it easier to remember and put a quote around the variable value regardless.

You may have also noticed the {{ inventory_hostname }} reference, which is not declared in the playbook. It is one of the default variables that Ansible provides for you automatically, and it is sometimes referred to as the magic variable.

There are not many magic variables, and you can find the list in the documentation (http://docs.ansible.com/ansible/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts).

We have declared variables in an inventory file in the previous section:

[nexus:vars]
username=cisco
password=cisco

[nexus_by_name]
switch1 ansible_host=192.168.199.148
switch2 ansible_host=192.168.199.149

To use the variables in the inventory file instead of declaring them in the playbook, let's add the group variables for [nexus_by_name] in the host file:

[nexus_by_name]
switch1 ansible_host=192.168.199.148
switch2 ansible_host=192.168.199.149

[nexus_by_name:vars]
username=cisco
password=cisco

Then, modify the playbook to match what we can see here in cisco_2.yml, to reference the variables:

---
- name: Configure SNMP Contact
hosts: "nexus_by_name"
gather_facts: false
connection: local

vars:
cli:
host: "{{ ansible_host }}"
username: "{{ username }}"
password: "{{ password }}"
transport: cli

tasks:
- name: configure snmp contact
nxos_snmp_contact:
contact: TEST_1
state: present
provider: "{{ cli }}"

register: output

- name: show output
debug:
var: output

Notice that in this example, we are referring to the nexus_by_name group in the inventory file, the ansible_host host variable, and the username and password group variables. This is a good way of hiding the username and password in a write-protected file and publish the playbook without the fear of exposing your sensitive data.

To see more examples of variables, check out the Ansible documentation (http://docs.ansible.com/ansible/playbooks_variables.html).

To access complex variable data that's provided in a nested data structure, you can use two different notations. Noted in the nxos_snmp_contact task, we registered the output in a variable and displayed it using the debug module. You will see something like the following during playbook execution:

    TASK [show output]  
*************************************************************
ok: [switch1] => {
"output": {
"changed": false,
"end_state": {
"contact": "TEST_1"
},
"existing": {
"contact": "TEST_1"
},
"proposed": {
"contact": "TEST_1"
},
"updates": []
}
}

In order to access the nested data, we can use the following notation, as specified in cisco_3.yml:

msg: '{{ output["end_state"]["contact"] }}'
msg: '{{ output.end_state.contact }}'

You will receive just the value indicated:

TASK [show output in output["end_state"]["contact"]]   
***************************
ok: [switch1] => {
"msg": "TEST_1"
}
ok: [switch2] => {
"msg": "TEST_1"
}

TASK [show output in output.end_state.contact]
*********************************
ok: [switch1] => {
"msg": "TEST_1"
}
ok: [switch2] => {
"msg": "TEST_1"
}

Lastly, we mentioned variables can also be stored in a separate file. To see how we can use variables in a role or included file, we should get a few more examples under our belt, because they are a bit complicated to start with. We will see more examples of roles in Chapter 5, The Python Automation Framework Beyond Basics.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.192.167