Skip to content

Commit

Permalink
Update description and documentation
Browse files Browse the repository at this point in the history
* Short description of alternative filter.
* One more example how to use the alternative filter (dynamically
  specify match pattern for keys at runtime).

MOD: README.md
MOD: plugins/filter/aci2.py
  • Loading branch information
velotiger committed Apr 9, 2021
1 parent be9ffa6 commit f560ced
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Ansible Role: aci-model
A comprehensive Ansible role to model and deploy Cisco ACI fabrics.
A comprehensive Ansible role to model and deploy Cisco ACI fabrics and a custom Ansible filter for structured data.

This role provides an abstraction layer that is convenient to use. By providing your required configuration (a structured dataset) in your inventory this role will perform the needed actions to ensure that configuration is deployd on your ACI infrastructure.
This role provides an abstraction layer that is convenient to use. By providing your required configuration (a structured dataset) in your inventory this role will perform the needed actions to ensure that configuration is deployed on your ACI infrastructure.

Using this role you can easily set up demo environment, maintain a lab or use it as the basis for your in-house ACI infrastructure. It can help you understand how ACI works while prototyping and testing. No prior Ansible or ACI knowledge is required to get started.

Expand Down Expand Up @@ -38,6 +38,14 @@ You need to configure your Ansible to find this Jinja2 filter. There are two way

Because of its general usefulness, we are looking into making this *aci_listify* filter more generic and make it part of the default Ansible filters.

#### The alternative filter plugin
The alternative filter *aci_listify2* (file: *plugins/filter/aci2.py*) is installed in the same manner as the original filter. It provides the following enhancements:

* Data structure need not be an alternating tree of dict/list. The tree may contain lists/dicts in any order.
* You can append a regex to each key so that only key values that match the regex will appear in the output.
* This is documented in the file *plugins/filter/aci2.py* itself.

The filter does not depend on this Ansible role. It can be used in any Ansible task to extract a list of items from a structured dict. For this purpose, it suffices to install the filter. You need neither the role nor the playbook or the example inventory.

## Using the example playbook

Expand Down
54 changes: 48 additions & 6 deletions plugins/filter/aci2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright: (c) 2020, Tilmann Boess <tilmann.boess@hr.de>
# Copyright: (c) 2020-2021, Tilmann Boess <tilmann.boess@hr.de>
# Based on: (c) 2017, Ramses Smeyers <rsmeyers@cisco.com>

# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
Expand Down Expand Up @@ -26,11 +26,53 @@ def Lister(Dict, *Keys):
– You can append a regex to each key (separated by an =–sign). Only keys
whose name-attribute matches the regex will be included in the result.
If the regex is omitted, all keys will be included (backwards compatible).
Example:
"{{ aci_topology|aci_listify2('access_policy', 'interface_policy_profile=.+998', 'interface_selector') }}"
All paths in the output match interface policy profiles that end in «998».
E.g. interface selectors below a non-matching interface policy profile
will be suppressed from the output.
Examples:
1. Simple static specification:
loop: "{{ aci_topology|aci_listify2('access_policy', 'interface_policy_profile=.+998', 'interface_selector') }}"
All paths in the output match interface policy profiles that end in «998».
E.g. interface selectors below a non-matching interface policy profile
will be suppressed from the output.
2. Dynamic specification:
loop: "{{ LEAFID_ROOT|aci_listify2(leaf_match, port_match, 'type=switch_port') }}"
vars:
leaf_match: "leafid={{ outer.leafid_Name }}"
port_match: "port={{ outer.leafid_port_Name }}"
Here the regex's for the leafid and the port are determined at runtime in an
outer task. The outer task sets the dict 'outer' and this dict is referenced
here.
'LEAFID_ROOT' is the dict in which to look for the following hierarchy:
leafid:
- Name: 101
port:
- Name: 1
type:
- Name: switch_port
- Name: 101
port:
- Name: 2
type:
- Name: port_channel
(and so on for all leaf-switches and ports)
This matches only if:
* leafid matches the leafid delivered by the outer task.
* port matches the port delivered by the outer task.
* The port shall be configured as a simple switchport (not a channel).
The outer task could be:
- name: "example outer task"
include_tasks:
file: inner.yaml
loop: "{{ portlist }}"
loop_control:
loop_var: outer
vars:
portlist:
- leafid.Name: '10.'
leafid_port_Name: '1'
- leafid.Name: '203'
leafid_port_Name: '42'
The dict 'portlist' need not be specified here as task variable.
You can provide it as extra var on the command line and thus specify
dynamically which ports shall be configured.
Returns:
- list of dicts (key/value-pairs); given keys are concatenated with '_' to form
a single key. Example: ('tenant' , 'app' , 'epg') results in 'tenant_app_epg'.
Expand Down

0 comments on commit f560ced

Please sign in to comment.