How can I parse metadata from show version (cisco ios) using ansible - parsing

Here is my playbook
The return of output.stdout is a list that's why I call it by index of 0
- name: "GENERATE VERSION REPORT"
hosts: all
gather_facts: false
roles:
- ansible-network.network-engine
tasks:
- name: CAPTURE SHOW VERSION
ios_command:
commands:
- show version
register: output
- name: Display output
debug:
var: output.stdout
- name: PARSE THE RAW OUTPUT
command_parser:
file: "/home/nettools/ansible/parsers/show_version.yaml"
content: "{{ output.stdout[0] }}"
- name: DISPLAY THE PARSED DATA
debug:
var: version_facts
Here is the show_version.yaml file
I use regex101.com to check and it is all ok but I get null value for all keys.
---
- name: parser meta data
parser_metadata:
version: 1.0
command: show version
network_os: cisco.ios.ios
- name: match version values
pattern_group:
- name: match name
pattern_match:
regex: "^(\\S+) uptime is"
content: "{{ item }}"
register: name
- name: match IMAGE FILE
pattern_match:
regex: "System image file is (\\S+)"
content: "{{ item }}"
register: image
- name: match VIRTUAL INTERFACES
pattern_match:
regex: "^(\\S+) Virtual Ethernet interfaces"
content: "{{ item }}"
register: virethint
- name: match GIGABIT INTERFACES
pattern_match:
regex: "^(\\S+) Gigabit Ethernet interfaces"
content: "{{ item }}"
register: gigethint
- name: match FAST INTERFACES
pattern_match:
regex: "^(\\S+) FastEthernet interfaces"
content: "{{ item }}"
register: fastethint
- name: match SERIAL NUMBER
pattern_match:
regex: "System serial number.*: (\\S+)"
content: "{{ item }}"
register: SN
- name: match MODEL NUMBER
pattern_match:
regex: "Model number.*: (\\S+)"
content: "{{ item }}"
register: MODEL
- name: match VERSION
pattern_match:
regex: "Cisco IOS Software, .+Version (\\S+),"
content: "{{ item }}"
register: version
- name: generate json data structure
json_template:
template:
- key: "{{ item.name.matches.0 }}"
object:
- key: element
object:
- key: name
value: "{{ item.name.matches.0 }}"
- key: image
value: "{{ item.image.matches.0 }}"
- key: virethint
value: "{{ item.virethint.matches.0 }}"
- key: gigethint
value: "{{ item.gigethint.matches.0 }}"
- key: fastethint
value: "{{ item.fastethint.matches.0 }}"
- key: SN
value: "{{ item.SN.matches.0 }}"
- key: MODEL
value: "{{ item.MODEL.matches.0 }}"
- key: version
value: "{{ item.version.matches.0 }}"
export: yes
register: version_facts
Here is the output
I want to get the name, the model, the serial number, the number of fast, giga and virtual interfaces and the version of course
task path: /home/nettools/ansible/playbook/cisco_playbook/sh_ver_parsed.yml:19
<10.224.12.4> attempting to start connection
<10.224.12.4> using connection plugin ansible.netcommon.network_cli
<10.224.12.4> found existing local domain socket, using it!
<10.224.12.4> updating play_context for connection
<10.224.12.4>
<10.224.12.4> local domain socket path is /root/.ansible/pc/5d7175bc45
processing directive: parser meta data
command_parser: using parser version 1.0
processing directive: match version values
command_parser: starting pattern_match [match name] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match IMAGE FILE] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match VIRTUAL INTERFACES] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match GIGABIT INTERFACES] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match FAST INTERFACES] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match SERIAL NUMBER] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match MODEL NUMBER] in pattern_group
command_parser: loop_var is item
command_parser: starting pattern_match [match VERSION] in pattern_group
command_parser: loop_var is item
processing directive: generate json data structure
ok: [ITG15019] => {
"ansible_facts": {
"version_facts": {
"null": {
"element": {
"MODEL": null,
"SN": null,
"fastethint": null,
"gigethint": null,
"image": null,
"name": null,
"version": null,
"virethint": null
}
}
}
},
"changed": false,
"included": [
"/home/nettools/ansible/parsers/show_version.yaml"
]
}
ok: [ITG15019] => {
"output.stdout": [
"Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.0(2)EX1, RELEASE SOFTWARE (fc1)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2013 by Cisco Systems, Inc.\nCompiled Fri 28-Jun-13 13:20 by prod_rel_team\n\nROM: Bootstrap program is Alpha board boot loader\nBOOTLDR: C2960X Boot Loader (C2960X-HBOOT-M) Version 15.0(2r)EX, RELEASE SOFTWARE (fc1)\n\nDTY-W0I030 uptime is 2 weeks, 3 days, 16 hours, 28 minutes\nSystem returned to ROM by power-on\nSystem restarted at 22:34:39 cet Fri Oct 8 2021\nSystem image file is \"flash:/c2960x-universalk9-mz.150-2.EX1/c2960x-universalk9-mz.150-2.EX1.bin\"\n\n\nThis product contains cryptographic features and is subject to United\nStates and local country laws governing import, export, transfer and\nuse. Delivery of Cisco cryptographic products does not imply\nthird-party authority to import, export, distribute or use encryption.\nImporters, exporters, distributors and users are responsible for\ncompliance with U.S. and local country laws. By using this product you\nagree to comply with applicable laws and regulations. If you are unable\nto comply with U.S. and local laws, return this product immediately.\n\nA summary of U.S. laws governing Cisco cryptographic products may be found at:\nhttp://www.cisco.com/wwl/export/crypto/tool/stqrg.html\n\nIf you require further assistance please contact us by sending email to\nexport#cisco.com.\n\ncisco WS-C2960X-48LPS-L (APM86XXX) processor (revision V01) with 524288K bytes of memory.\nProcessor board ID FOC1728W1W1\nLast reset from power-on\n2 Virtual Ethernet interfaces\n1 FastEthernet interface\n156 Gigabit Ethernet interfaces\nThe password-recovery mechanism is enabled.\n\n512K bytes of flash-simulated non-volatile configuration memory.\nBase ethernet MAC Address : F8:4F:57:47:EA:00\nMotherboard assembly number : 73-14191-03\nPower supply part number : 341-0528-01\nMotherboard serial number : FOC172615CP\nPower supply serial number : LIT17230R2W\nModel revision number : V01\nMotherboard revision number : A0\nModel number : WS-C2960X-48LPS-L\nDaughterboard assembly number : 73-14200-03\nDaughterboard serial number : FOC172635D1\nSystem serial number : FOC1728W1W1\nTop Assembly Part Number : 800-38006-01\nTop Assembly Revision Number : A0\nVersion ID : V01\nCLEI Code Number : CMMLP00ARA\nDaughterboard revision number : A0\nHardware Board Revision Number : 0x05\n\n\nSwitch Ports Model SW Version SW Image \n------ ----- ----- ---------- ---------- \n* 1 52 WS-C2960X-48LPS-L 15.0(2)EX1 C2960X-UNIVERSALK9-M \n 2 52 WS-C2960X-48LPS-L 15.0(2)EX1 C2960X-UNIVERSALK9-M \n 3 52 WS-C2960X-48LPS-L 15.0(2)EX1 C2960X-UNIVERSALK9-M \n\n\nSwitch 02\n---------\nSwitch Uptime : 2 weeks, 3 days, 16 hours, 29 minutes \nBase ethernet MAC Address : 50:17:FF:F8:E7:00\nMotherboard assembly number : 73-14191-03\nPower supply part number : 341-0528-01\nMotherboard serial number : FOC17330K1C\nPower supply serial number : LIT17290RVF\nModel revision number : A0\nMotherboard revision number : A0\nModel number : WS-C2960X-48LPS-L\nDaughterboard assembly number : 73-14200-03\nDaughterboard serial number : FOC173135JL\nSystem serial number : FOC1733S1EA\nTop assembly part number : 800-38006-01\nTop assembly revision number : A0\nVersion ID : V01\nCLEI Code Number : CMMLP00ARA\nDaughterboard revision number : A0\n\nSwitch 03\n---------\nSwitch Uptime : 2 weeks, 3 days, 16 hours, 29 minutes \nBase ethernet MAC Address : 50:17:FF:83:F2:00\nMotherboard assembly number : 73-14191-03\nPower supply part number : 341-0528-01\nMotherboard serial number : FOC17330K9R\nPower supply serial number : LIT17290RLR\nModel revision number : A0\nMotherboard revision number : A0\nModel number : WS-C2960X-48LPS-L\nDaughterboard assembly number : 73-14200-03\nDaughterboard serial number : FOC173134P7\nSystem serial number : FOC1733S1EP\nTop assembly part number : 800-38006-01\nTop assembly revision number : A0\nVersion ID : V01\nCLEI Code Number : CMMLP00ARA\nDaughterboard revision number : A0\n\nConfiguration register is 0xF"
]
}
Why I am getting null value ?

i think you have to set the option export:
- name: match version values
pattern_group:
- name: match name
pattern_match:
regex: "^(\\S+) uptime is"
content: "{{ item }}"
register: name
export: yes
Without this directive the variable and value contained will not be sent back to the playbook for further processing.
Second, i dont see the utility to have content: "{{ item }}"?
- name: match version values
pattern_group:
- name: match name
pattern_match:
regex: "^(\\S+) uptime is"
register: name
i suggest you to play the playbook with -vvv (very verbose) to trap some matching problems
so i see you have set export to playbook json_template, i think is right too..
EDIT
i think ^ its not seen as start of line
could you try: regex: "\n(\\S+) uptime is"

I use the export yes in the pattern_group #frenchy and register the value in facts and
it is working well. You have right I don't need item.
---
- name: parser meta data
parser_metadata:
version: 1.0
command: show version
network_os: cisco.ios.ios
- name: match version values
pattern_group:
- name: match name
pattern_match:
regex: "\n(\\S+) uptime is"
register: name
- name: match IMAGE FILE
pattern_match:
regex: "System image file is (\\S+)"
register: image
- name: match VIRTUAL INTERFACES
pattern_match:
regex: "^(\\S+) Virtual Ethernet"
register: virethint
- name: match GIGABIT INTERFACES
pattern_match:
regex: "^(\\S+) Gigabit Ethernet"
register: gigethint
- name: match FAST INTERFACES
pattern_match:
regex: "^(\\S+) FastEthernet"
register: fastethint
- name: match SERIAL NUMBER
pattern_match:
regex: "System serial number.*: (\\S+)"
register: SN
- name: match MODEL NUMBER
pattern_match:
regex: "Model number.*: (\\S+)"
register: MODEL
- name: match VERSION
pattern_match:
regex: "Cisco IOS Software, .+Version (\\S+),"
register: version
register: facts
export: yes
- name: generate json data structure
json_template:
template:
- key: "{{ facts.name.matches.0 }}"
object:
- key: element
object:
- key: name
value: "{{ facts.name.matches.0 }}"
- key: image
value: "{{ facts.image.matches.0 }}"
- key: virethint
value: "{{ facts.virethint.matches.0 }}"
- key: gigethint
value: "{{ facts.gigethint.matches.0 }}"
- key: fastethint
value: "{{ facts.fastethint.matches.0 }}"
- key: SN
value: "{{ facts.SN.matches.0 }}"
- key: MODEL
value: "{{ facts.MODEL.matches.0 }}"
- key: version
value: "{{ facts.version.matches.0 }}"
export: yes
register: version_facts

Related

InfluxDB 1.8 - SELECT exact

I'm trying to discern if it is possible to query InfluxDB to have an exact match on tags without having to first query InfluxDB for the TAG KEYS to generate my query.
Here is an example to showcase what I'm trying to accomplish,
Connected to http://localhost:8086 version 1.10.0
InfluxDB shell version: 1.10.0
> create database so
> use so
Using database so
> INSERT cpu,cpu=cpu0,env=intg,host=is-nflxts101t time_system=13592
> INSERT cpu,env=intg,host=is-nflxts101t time_system=134
SELECT * FROM cpu
name: cpu
time cpu env host time_system
---- --- --- ---- -----------
1668608108642977000 cpu0 intg is-nflxts101t 13592
1668608113752018000 intg is-nflxts101t 134 # <--- We want to get this line ONLY
The goal is to get the final line where cpu isn't specified.
The naive query gives us the complete set of rows, including the one we do not want,
> SELECT * FROM cpu WHERE "env"='intg' AND "host"='is-nflxts101t'
name: cpu
time cpu env host time_system
---- --- --- ---- -----------
1668608108642977000 cpu0 intg is-nflxts101t 13592 # <--- undesired
1668608113752018000 intg is-nflxts101t 134
and while I could first fetch all TAG KEYS to programatically generate the query,
> SELECT * FROM cpu WHERE "env"='intg' AND "host"='is-nflxts101t' AND "cpu" = ''
name: cpu
time cpu env host time_system
---- --- --- ---- -----------
1668608113752018000 intg is-nflxts101t 134
in my application code I was hoping there was/is a way to express this psuedo-query,
> SELECT * FROM cpu WHERE EXACT "env"='intg' AND "host"='is-nflxts101t'
name: cpu
time cpu env host time_system
---- --- --- ---- -----------
1668608113752018000 intg is-nflxts101t 134
Is there any way to accomplish this? Or am I stuck with fetching the keys first?
Your sample should be good enough to filter out null-value tag with other conditions:
SELECT * FROM cpu WHERE "env"='intg' AND "host"='is-nflxts101t' AND "cpu" = ''
as for tags, doing WHERE some_tag = '' will match rows for which the tag has no value. (The tag value will still be returned as null in the response, though, not as the empty string, because internally-consistent type systems are for pansies.)

grep between pattern and exclude start/end pattern in output

I have file.txt from which I need to grep first occurrence of a pattern. How can I grep and get matched string only ':whitespace' and 'end of line'
I m trying below command
cat file.txt | grep -m1 -P "(:\s+).*ccas-apache$"
But it gives me
name: nginx-ccas-apache
and I want is
nginx-ccas-apache
file.txt
pod: nginx-ccas-apache-0
name: nginx-ccas-apache
image: myregnapq//ccas_apache
name: nginx-filebeat
pod: nginx-ccas-apache-1
name: nginx-ccas-apache
image: myregnapq/ccas_apache
name: nginx-filebeat
Another approach using sed:
sed -En '/^[[:space:]]+name:[[:space:]](.*ccas-apache)$/{s//\1/p;q}' file.txt
Explanation
-En Use extended regexp with -E and prevent the default printing of a line by sed with -n
/^[[:space:]]+name:[[:space:]](.*ccas-apache)$/ The pattern that specifies what to match
If the previous pattern matched, run commands between the curly brackets
s//\1/p Use the last matched pattern with // and replace with group 1. Then print the pattern space with p
q exit sed
The regex matches:
^ Start of string
[[:space:]]+name:[[:space:]] Match name: with leading spaces and single space after
(.*ccas-apache) Capture group 1, match optional chars and ccas-apache
$ End of string
Output
nginx-ccas-apache
Note that you don't have to use cat
See an online demo.
Using grep
$ grep -Pom1 'name: \K.*$' file.txt
nginx-ccas-apache
You can use awk, too:
awk -F: '/:[[:space:]].*ccas-apache$/{sub(/^[[:space:]]+/, "", $2); print $2; exit}' file
Details:
-F: - a colon is used as a field separator
:[[:space:]].*ccas-apache$ - searches for a line with :, a whitespace, then any text, ccas-apache at the end of the string, and once found
sub(/^[[:space:]]+/, "", $2) - remove the initial whitespaces from Field 2
print $2 - then print the Field 2 value
exit - stop processing the file.
See the online demo:
#!/bin/bash
s='pod: nginx-ccas-apache-0
name: nginx-ccas-apache
image: myregnapq//ccas_apache
name: nginx-filebeat
pod: nginx-ccas-apache-1
name: nginx-ccas-apache
image: myregnapq/ccas_apache
name: nginx-filebeat'
awk -F: '/:[[:space:]].*ccas-apache$/{sub(/^[[:space:]]+/, "", $2); print $2; exit}' <<< "$s"
Output: nginx-ccas-apache
INPUT
pod: nginx-ccas-apache-0
name: nginx-ccas-apache
image: myregnapq//ccas_apache
name: nginx-filebeat
pod: nginx-ccas-apache-1
name: nginx-ccas-apache
image: myregnapq/ccas_apache
name: nginx-filebeat
CODE
enter any properly-escaped pattern for __ that includes the string tail $
3 ways of saying the same thing
any one solution works in gawk, mawk-1, mawk-2, or macos nawk
mawk '_{exit} _=$(NF=NF)~__' FS='^.*[ \t]' __='ccas-apache$' OFS=
or
gawk '_{exit} NF*=_=$(NF)~__' FS='^.*[ \t]' __='ccas-apache$' OFS=
or
nawk '_{exit} _=NF*=$NF~__' FS='^.*[ \t]' __='ccas-apache$' OFS=
OUTPUT
nginx-ccas-apache
GENERIC SOLUTION
not just at the tail
this time enter pattern at FS
CODE
{m,g}awk '_{exit} _=(!_<NF)*sub("[^ \t]*"(FS)"[^ \t]*","\4&\4")*\
gsub("^[^\4]*\4|\4[^\4]*$","")' FS='your_pattern_here'
OUTPUT
FS='image'
>>> `image:`
FS='myregnapq'
>>> `myregnapq//ccas_apache`
With your shown samples please try following awk code.
awk -F':[[:space:]]+' '
$1~/^[[:space:]]+name$/ && $2~/^[^-]*-ccas-apache$/{
print $2
exit
}
' Input_file
Explanation: Simple explanation would be, setting field separator as colon followed by space(1 or more occurrences). In main program checking condition if first field matches regex starts with space followed by name AND 2nd field matches regex ^[^-]*-ccas-apache$ then printing 2nd field of that line and `exit from program.

Parse YAML using shell

I have a yaml something of this sort and need to parse and get the value of 'url' here.
name: Yaml_Test
servers:
- name: host_ip
host: host_name
port: 443
scheme: https
variables:
- constant:
name: url
value: https://url_here
With the current versions of both kislyuk/yq and mikefarah/yq, use select to filter the array items:
.variables[].constant | select(.name == "url").value
https://url_here
Using kislyuk/yq, you may want to add the -r option to output raw text:
yq -r '…' file.yaml
Using an older version of mikefarah/yq, you need to specify the command e or eval:
yq e '…' file.yaml
Edit: Although not recommended, here's as requested in a comment a grep-only solution which heavily relies on how the YAML document is represented textually, based on the sample provided (i.e. no other occurrence of name: url etc.):
grep -A1 'name: url' file.yaml | grep -o 'http.*'
https://url_here

Show a match (grep) and show one column of the matched line

Say I have a following text file (Nmap's .gnmap) and what I want is to show my match and corresponding IP addres. I.e. only show 22/open and 2000/open and also IP of those two ports. I need this result:
10.10.10.1 22/open 2000/open
10.10.10.2 2000/open
To get IPs is simple grep -iE "22/open|2000/open" file, but how do i also display IP? I need following output (exact extra characters does not matter, as long as each line contains IP and port):
Example source file:
Host: 10.10.10.1 () Ports: 22/open/tcp//ssh///, 80/open/tcp//http///, 113/closed/tcp//ident///, 443/open/tcp//https///, 541/open/tcp//uucp-rlogin///, 2000/open/tcp//cisco-sccp/// Ignored State: filtered (4994)
Host: 10.10.10.2 () Ports: 113/closed/tcp//ident///, 2000/open/tcp//cisco-sccp/// Ignored State: filtered (4998)
Could you please try following.
awk '
match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/){
ip_found=substr($0,RSTART,RLENGTH)
}
{
while(match($0,/22\/open|2000\/open/)){
val=(val?val OFS:"")substr($0,RSTART,RLENGTH)
$0=substr($0,RSTART+RLENGTH)
}
if(ip_found){
print ip_found,val
}
ip_found=val=""
}
' Input_file
Output will be as follows.
10.10.10.1 22/open 2000/open
10.10.10.2 2000/open

How to search for files with a pattern of 2 consecutive new lines & modify the succeeding line?

I have a few directories with a bunch of files that I need to change. That change involves me finding the files that includes the selector and service labels:
selector:
service: XXXXX
and replacing the service label with app:
selector:
app: XXXXX
Btw, none of the solutions in this similar stack overflow thread work.
In case You wanna AWK (gawk) solution. Here it is.
Considering input per Your question:
$ cat v1mg1rl.txt
application:
id: 0
service: WWWWW
selector:
id: 1
service: XXXXX
cartridge:
id: 2
service: ZZZZZ
AWK:
$ awk '/^[^ ]+/ { isselector=0; } /^selector:/ { isselector=1; } /^ +service: / { if (isselector) sub(/service: /,"app: "); } { print($0); }' v1mg1rl.txt
application:
id: 0
service: WWWWW
selector:
id: 1
app: XXXXX
cartridge:
id: 2
service: ZZZZZ

Resources