Skip to content

Commit

Permalink
Pull in arista-ansible-role-test updates
Browse files Browse the repository at this point in the history
  • Loading branch information
grybak-arista committed Jun 15, 2016
2 parents 047b130 + b561333 commit 110c766
Show file tree
Hide file tree
Showing 2 changed files with 305 additions and 32 deletions.
277 changes: 257 additions & 20 deletions test/arista-ansible-role-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ Arista Roles for Ansible - Development Guidelines
* [Overview] (#overview)
* [Details] (#details)
2. [Developing Arista Roles For Ansible] (#developing-arista-roles-for-ansible)
* [Role Development Guidelines] (#role-development-guidelines)
* [Role Test Development] (#role-test-development)
* [Development for arista-ansible-role-test] (#development-for-arista-ansible-role-test)
* [Preparing the Role Development Workspace] (#preparing-the-role-development-workspace)
* [Existing Role Development] (#existing-role-development)
* [New Arista Ansible role development] (#new-arista-ansible-role-development)
* [Role Development Guidelines] (#role-development-guidelines)
* [Define the role's task list] (#define-the-roles-task-list)
* [Implement jinja2 templates for the role's tasks] (#implement-jinja2-templates-for-the-roles-tasks)
* [Include supporting files and documentation] (#include-supporting-files-and-documentation)
* [Role Test Development] (#role-test-development)
* [Development for arista-ansible-role-test] (#development-for-arista-ansible-role-test)



Expand Down Expand Up @@ -83,31 +89,262 @@ used for the backups, as well as how to restore the device and delete the backup
Developing Arista roles for Ansible
-----------------------------------

#### Preparing the Role Development Workspace

##### Existing role development

To begin development on an existing Arista Ansible role, clone/fork
the role repository to your working environment, create a working
branch, and proceed with development.

##### New Arista Ansible role development

To begin development on a new Arista role for Ansible, initialize a
role directory using the `ansible-galaxy init` command.
```
ansible-galaxy init ansible-eos-newrole
```

This will create a directory named ansible-eos-newrole with the following
directory structure:
```
README.md
.travis.yml
defaults/
main.yml
files/
handlers/
main.yml
meta/
main.yml
templates/
tests/
inventory
test.yml
vars/
main.yml
```

Remove the .travis.yml file and the tests/ directory.

From an existing Arista role, copy the following files into the new
role's path, creating any missing directories as needed, and updating
file information to match the new role:

- .gitignore
- Makefile*
- files/README.md
- filter_plugins/config_block.py
- handlers/main.yml
- meta/main.yml*
- test/fixtures/hosts


```
Note: An asterisk (*) indicates copied file should be reviewed for changes
specific to the new role, such as updating the role name.
```

#### Role development guidelines

* Copy the following files from an existing Ansible EOS role into the
current role:

* .gitignore
* Makefile*
* defaults/main.yml*
* files/README.md
* filter_plugins/config_block.py
* handlers/main.yml*
* meta/main.yml*
* tasks/main.yml*
* templates/README.md
* vars/main.yml*
* test/fixtures/hosts
An Arista role for Ansible consists of a list of tasks (tasks/main.yml) and
associated jinja2 templates (templates/*.j2) that will process a set of host
variables defined in an Ansible host_vars file.

The development of an Arista role for Ansible includes defining the set of
tasks for the role, implementing the jinja2 templates for each of the
role-specific tasks, and providing any supporting files and documentation for
the role.

##### Define the role's task list

The task list for the role is defined in tasks/main.yml.

Every Arista role should contain two tasks at the top of the list which will
gather the current running-config from the device and store it in the variable
`_eos_config`.

```
- name: Gather EOS configuration
eos_command:
commands: 'show running-config all | exclude \.\*'
provider: "{{ provider | default(omit) }}"
auth_pass: "{{ auth_pass | default(omit) }}"
authorize: "{{ authorize | default(omit) }}"
host: "{{ host | default(omit) }}"
password: "{{ password | default(omit) }}"
port: "{{ port | default(omit) }}"
transport: "cli"
use_ssl: "{{ use_ssl | default(omit) }}"
username: "{{ username | default(omit) }}"
register: output
no_log: "{{ no_log | default(true) }}"
when: _eos_config is not defined
- name: Save EOS configuration
set_fact:
_eos_config: "{{ output.stdout[0] }}"
no_log: "{{ no_log | default(true) }}"
when: _eos_config is not defined
```

Then call each task that will be defined for the role itself, using the
following format:

```
- name: Arista EOS < XXX task description >
eos_template:
src: XXXtemplatenameXXX.j2
include_defaults: true
config: "{{ _eos_config | default(omit) }}"
auth_pass: "{{ auth_pass | default(omit) }}"
authorize: "{{ authorize | default(omit) }}"
host: "{{ host | default(omit) }}"
password: "{{ password | default(omit) }}"
port: "{{ port | default(omit) }}"
provider: "{{ provider | default(omit) }}"
transport: 'cli'
use_ssl: "{{ use_ssl | default(omit) }}"
username: "{{ username | default(omit) }}"
notify: save running config
```

Refer to existing Arista roles and the Ansible documentation for examples on
using when, with_items, and other conditional statements to refine the
execution of the tasks in the role.

Occasionally, a task may result in a change that needs to be propagated to the
stored _eos_config (tasks affect the running-config, not the stored _eos_config).
This may occur when an individual task produces results that are necessary may
not be in the initial configuration, but have updated the running-config. In
this instance, a block statement may be used to update the stored configuration
if a change has occurred. Refer to an existing Arista role, such as
ansible-eos-vxlan, for an example of how this might be handled.

##### Implement jinja2 templates for the role's tasks

Each task in the role's task list (other than those tasks for retrieving and
storing the running-config) should have a jinja2 file listed as the src entry
(XXXtemplatenameXXX.j2 in the example above). The jinja2 template files
take information from the passed in host_var definition and convert those to
a set of configuration entries that match those lines as they would be
returned from a `show running-config all` command on EOS.

So, for example, a template that would set the hostname on the device would
return the following line.

```
Note: Asterisk (*) indicates file should be reviewed for changes specific
to the new role, such as updating the role name.
hostname <newhostname>
```

A template that would configure elements of a BGP setup would require indented
information in addition to the initial `router bgp` call.

```
router bgp 113
no shutdown
router-id 13.13.13.13
maximum-paths 3 ecmp 14
```

Note that indented lines must match the three-space indentation exactly as is
returned by the EOS configuration output. The information returned from the
template is matched to the stored configuration to determine what calls will
be sent to the device.

To maintain consistency, please follow the following formatting guidelines
for jinja2 templates included with Arista roles.

- Each template should contain the file name marker, and set trim_blocks and
lstrip_blocks to false at the top of the file
- Indentation should be 3 spaces for all lines in the file
- Jinja filter pipes should be surrounded by a single space
- Output lines from the template (the lines that will be returned and
compared with the stored config) should be preceeded and followed by
a single blank line
- Multiple sequential output lines may be grouped and the entire
group enclosed by the single blank lines
- Comments that span multiple lines should have each line begin with
the Jinja2 comment delimiter
- The closing comment delimiter is only required on the last line
of the multi-line comment
- Comments should be used liberally to provide clarification to
the process taking place in the template
- Mark the end of for loops and if blocks where useful
- Explain the purpose of filters being used or sections of code

Below is a short example of the formatting for a template file. Refer to
existing Arista roles template files for additional examples.

*XXX File structure, formatting guidelines, and other info goes here*
```
! templates/XXXtest.j2
#jinja2: trim_blocks: False
#jinja2: lstrip_blocks: False
{% set state = item.state | default(eos_XXX_default_state) %}
{% set name = item.name %}
{# add a comment that spans several lines to keep the formatting
{# and indentation across the multiple lines, making sure to close
{# the comment after the final line #}
{# set the netaddr by filtering through ipsubnet. note the space around the pipe #}
{% set netaddr = srcaddr | ipsubnet(srcprefixlen) %}
{% if not netaddr %}
{# if srcprefixlen is 32, netaddr is False, so define the netaddr as a host IP #}
{% set netaddr = "host %s" % srcaddr %}
{% endif %}
{# set the seqno and log strings to be used in the actual rule #}
{% set seqno_rule = "%s " % seqno if seqno else '' %}
{% set log_rule = ' log' if log else '' %}
{# build the rule command line #}
{% set rule = "%s%s %s%s" % (seqno_rule, action, netaddr, log_rule) %}
{# send the rule - surround the output by blank lines #}
{{ rule }}
{# the comments around the output lines are not required, but are
{# for the example only #}
{# make sure the indentation is correct for an EOS configuration #}
{% if something %}
{% if x == y %}
hostname {{ x }} <-- note the indentation
{% else %}
hostname {{ abc }}
{% endif %} {# x == y #}
{% endif %} {# something #}
```

##### Include supporting files and documentation

Occasionally, a default value is desired for a variable within an Arista role,
as in the `set state` line in the example above. These defaults may be set
in the defaults/main.yml file, and should be explanatory in their naming.
Default values do not fill in missing host_vars values automatically, but must
be pulled in through a default filter as shown in the example.

There may also arise the need to implement a specific filter to be used by the
role. Filters are written in python and located in the filter_plugins
directory. The config_block filter is included in all roles, and contains
filters to return a block of configuration from the _eos_config file, as well
as regular expression search and findall filters for matching lines in the
config. Additional filters may be implemented as necessary. See the range filter
in ansible-eos-mlag for an example.

Finally, make sure the README.md is properly updated for the role. Include a
brief description of the purpose of the role, role variable information, any
dependencies, and an example playbook. Refer to existing Arista roles for
content examples, and sections that may be copied and pasted for ease.


#### Role test development
Expand Down
Loading

0 comments on commit 110c766

Please sign in to comment.