ansible-network / network-engine

This role provides the foundation for building network roles by providing modules and plugins that are common to all Ansible Network roles.
GNU General Public License v3.0
112 stars 53 forks source link

Feature request command parser combine multi-command facts into single json hierachy #213

Open nohir0 opened 5 years ago

nohir0 commented 5 years ago

ISSUE TYPE

ANSIBLE VERSION

ansible 2.7.5
ansible-network.network-engine, v2.7.2

Network OS

ios
ios-xe
ios-xr
nxos

SUMMARY

Currently one cli command output can be linked with one command parser instance (YAML file) to produce a structured json template structure based on the unstructured ASCII response of that single command. The "extend" directive has been added, which allows to extend an existing facts json structure, but always with a "separate key", right? (hope I did not miss something here)

An extend facts structure might look like this: The command based on the first fact list items is "show interface", the second command is "show interfaces status". Here we see the same key ("0/1") twice, because I extracted the interface ID as root key for both commands...

    "ansible_facts": {
        "device": {
            "extension": {
                "interface_facts": [
                    {
                        "0/1": {
                            "config": {
                                "description": "*** ROUTER ***", 
                                "mac": null, 
                                "mtu": "1500", 
                                "name": "0/1"
                            }, 
                            "stats": {
                                "drops_out": "21059", 
                                "input_errors": "0", 
                                "input_rate": "433000 bits/sec", 
                                "output_errors": "0", 
                                "output_rate": "38000 bits/sec"
                            }
                        }
                    }, 
[output of other interfaces omitted]
                    {
                        "0/1": {
                            "config": {
                                "status": "connected", 
                                "type": "10/100/1000BaseTX", 
                                "vlan": "trunk"
                            }
                        }
                    }, 
[output of other interfaces omitted]

Especially on network interfaces, one show command often do not give all required information for further ansible processing in efficient way. In above example the first command does not indicate if the interface operates as access port or trunk - the second command provides this information.

All these interface related commands have at least one common key together - the interface ID or Name. A new "combine" directive could match on a common key like that and merges the json structure based on that to unique data sets. This makes everything a lot easier for futher processing in ansible (like loops a.s.o)

E.g. a "show cdp neighbor" could also be included as a third show command - it would just be great to have CDP neighbors under the same interface related key. "show mac address-table" is another example.

EXPECTED RESULTS

If the command parser would allow to create a combined json structure based on one common key (like interface ID) using multiple commands - ansible could do things quite out of the box, that no other network mgmt tools can do until today!

    "ansible_facts": {
        "device": {
            "extension": {
                "interface_facts": [
                    {
                        "0/1": {
                            "config": {
                                "description": "*** ROUTER ***", 
                                "mac": null, 
                                "mtu": "1500", 
                                "name": "GigabitEthernet0/1"
                            }, 
                            "mac_addr": {
                                [
                                    "000c.29e3.3204",
                                    "709e.2998.b20c"
                                ]
                            },
                            "cdp_neig": {
                                    "name": router01,
                                    "interface": "GigabitEthernet1/1/1",
                                    "type": "C819G-4G"
                            }
                            "stats": {
                                "drops_out": "21059", 
                                "input_errors": "0", 
                                "input_rate": "433000 bits/sec", 
                                "output_errors": "0", 
                                "output_rate": "38000 bits/sec"
                            }
                        }
                    },
                    [further output omitted]

With this comprehensive facts I could do maximum flexible conditional configuration tasks, for example: Configure only active (up) trunk interfaces with routers as neighbors with setting "spanning-tree portfast trunk" - there are countless usecases...

I apologize my second Feature request in a short time, I currently do deep Ansible eval for network automation and this role is very promising! It makes great things possible without need to develop own modules (which is currently yet a kind of show stopper in regards to Ansible for Networkers)

LukeDRussell commented 5 years ago

We've managed to combine two IOS commands into a single object with extends. See https://github.com/Roshna-Raman/cisco_ios/blob/remotes/origin/f/parser_show_ip_route/vars/get_facts_command_map.yaml which calls both show ip route and show ip route vrf * to get all routing tables.

You can test it from my fork (https://galaxy.ansible.com/lukedrussell/cisco_ios) which tracks devel + parsers that we haven't got into upstream ansible-network repo yet.