I'm trying to use Ansible to hit a bunch (100+) Cisco Catalyst switches and check if they have a certain line card installed. Via SSH, this can be done with the "sh mod" command. I want to parse the output of that command in a playbook and then show the output of the command if a certain string matches. Right now with the playbook below I get the following error:
fatal: [redacted-hostname]: FAILED! => {"failed": true, "msg": "The
conditional check 'showmod | search(\"4548\")' failed. The error was:
Unexpected templating type error occurred on ({% if showmod |
search(\"4548\") %} True {% else %} False {% endif %}): expected
string or buffer\n\nThe error appears to have been in
'/etc/ansible/playbooks/linecard-4548.yaml': line 22, column 5, but
may\nbe elsewhere in the file depending on the exact syntax
problem.\n\nThe offending line appears to be:\n\n\n - debug:
\"msg='4548 Card Found'\"\n ^ here\n"}
Current playbook code:
---
- hosts: redacted-hostname
gather_facts: yes
connection: local
tasks:
- name: SYS | Define provider
set_fact:
provider:
host: "{{ inventory_hostname }}"
username: redacted-user
password: redacted-password
- name: IOS | Get Module List
ios_command:
provider: "{{ provider }}"
commands:
- sh mod | inc 4548
register: showmod
- debug: "msg='4548 Card Found'"
when: showmod.stdout | search("/4548/")
I've tried the when in the debug with and without the .stdout to no avail. I've done some research and the error I'm getting usually occurs when, in my case, showmod is undefined but it definitely is. If I replace the debug with the following snippet, the playbook runs fine but of course it'll print the output for every switch which isn't what I want.
- name: IOS | Show Output
debug:
var: showmod
Any suggestions?
ios_command returns stdout as list and stdout_lines as list of lists (whereas command module return stdout as string and stdout_lines as list).
So in your case, you may want to try:
- debug: "msg='4548 Card Found'"
when: showmod.stdout | join(" ") | search("/4548/")
Related
I try to test my audit activity on cisco device by the following task;
tasks:
- name: 1.1.1 Enable 'aaa new-model' (Scored)
ios_command:
commands: show running-config | incl aaa new-model
register: output1
- name: 1.1.1 Check results
delegate_to: localhost
lineinfile:
path: /tmp/Summary.txt
line: "1.1.1|Fail"
when: output1.stdout is 'no aaa new-model'
- name: 1.1.1 Check results
delegate_to: localhost
lineinfile:
path: /tmp/Summary.txt
line: "1.1.1|Pass"
when: output1.stdout is not 'no aaa new-model'
This activity will run ios command and register values after that I will check for condition and paste the result to my localhost(linux)
but I got this errors;
FAILED! => {"msg": "The conditional check 'output1.stdout is 'no aaa new-model'' failed. The error was: template error while templating string: expected token 'name', got 'string'. String: {% if output1.stdout is 'no aaa new-model' %} True {% else %} False {% endif %}\n\nThe error appears to be in '/etc/ansible/Cisco/1.1.yaml': line 15, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n register: output1\n - name: 1.1.1 Check results\n ^ here\n"}
Can anyone tell me what happens?
PS. My ansible version is 2.9.3
The result you stored in the "output1" variable is contained in 'output1.stdout[0]'.
'output1.stdout' is a list, and 'output1.stdout[0] is the string you are after.
In the below playbook, can someone please tell me what is wrong with the syntax of the final set_fact statement. If i explicitly specify the hostname R9 (as per the first set_fact), then it works without issue. But if I assign a variable to have a value of R9, and then use this in the final set_fact statement, I get the error shown below. Argh.
---
- hosts: all
gather_facts: no
vars:
ansible_network_os: ios
ansible_connection: network_cli
tasks:
- ios_command:
commands: show ip arp
register: results
- set_fact:
some_var: "{{ hostvars['R9'].results }}"
- set_fact:
hostname: "R9"
- set_fact:
another_var: "{{ hostvars['{{hostname}}'].results }}"
- debug:
var=some_var
- debug:
var=another_var
Error:
fatal: [R7]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: "hostvars['{{hostname}}']" is undefined
The error appears to be in '/root/ansible/Rapid/testsetfact.yml': line 20, column 6, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- set_fact:
^ here
fatal: [R9]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: "hostvars['{{hostname}}']" is undefined
The error appears to be in '/root/ansible/Rapid/testsetfact.yml': line 20, column 6, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- set_fact:
^ here
you can use the inventory_hostname for your purpose:
- set_fact:
another_var: "{{ hostvars[inventory_hostname].results }}"
I have this play to print certificate expire days. but its giving the AnsibleUndefined error. How to fix this error message.
Running this on Ansible 2.8 with Python 3.
Tasks
- name: Get a cert from an https port
get_certificate:
host: "{{ inventory_hostname }}"
port: 10250
delegate_to: "{{ inventory_hostname }}"
run_once: true
register: cert
- name: Cert output
debug:
msg: "{{ cert }}"
- name: How many days until cert expires
debug:
msg: "cert expires in: {{ expire_days }} days."
vars:
expire_days: "{{ (( cert.not_after | to_datetime('%Y%m%d%H%M%SZ')) - (ansible_date_time.iso8601 | to_datetime('%Y-%m-%dT%H:%M:%SZ')) ).days }}"
output and error message.
"failed": false,
"issuer": {
"CN": "kubernetes"
},
"not_after": "20290827151600Z",
"not_before": "20190830151600Z",
"serial_number": 552511748902341611097595302509251707409941832746,
"signature_algorithm": "sha256WithRSAEncryption",
version": 2
}
}
TASK [test : How many days until cert expires] ***********************************************************************************************************************************************
fatal: []: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: Unable to look up a name or access an attribute in template string ({{ (( cert.
not_after | to_datetime('%Y%m%d%H%M%SZ')) - (ansible_date_time.iso8601 | to_datetime('%Y-%m-%dT%H:%M:%SZ')) ).days }}).\nMake sure your variable name does not contain invalid characters like
'-': strptime() argument 1 must be str, not AnsibleUndefined\n\nThe error appears to be in '/playbooks/roles/test/tasks/main.yaml': line 23, column 3, but may\nbe elsewhere in the file depe
nding on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: How many days until cert expires\n ^ here\n"}
I was running gather_facts: no setting. When I change it to gather_facts: yes. Now its working as expected.
Im unable to search my output variable for a specified string that im using for a when statement. The code below is supposed to check for the string "distribute-list" in the output variable but when run the playbook it gives the error.
fatal: [192.168.3.252]: FAILED! => {"failed": true, "msg": "The conditional check 'output | search(\"distribute-list\")' failed. The error was: Unexpected templating type error occurred on ({% if output | search(\"distribute-list\") %} True {% else %} False {% endif %}): expected string or buffer\n\nThe error appears to have been in '/home/khibiny/test4.yml': line 26, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n"}
Here is the code that is causing issue:
- ios_command:
commands: show run | sec ospf
provider: "{{cli}}"
register: output
- debug:
msg: "{{output.stdout_lines}}"
when: output | search("distribute-list")
Would appreciate some help. Thanks in advance.
search expects string as input, but output is a dict with different properties.
You should be good with
when: output.stdout | join('') | search('distribute-list')
you need intermediate join here, because for ios-family modules stdout is a list of strings, and stdout_lines is a list of lists (whereas for usual command module stdout is a string and stdout_lines is a list of strings).
Im getting false positives with a when statement when searching for a not equal conditional in a output register. The reason is because part of the output contains the text that I am searching against but it is in another line. Below is a sample of my code.
tasks:
- ios_command:
commands: show run | inc logging host
provider: "{{cli}}"
register: run
- debug:
msg: "{{run.stdout_lines}}"
when: not run.stdout | join('') | search('192.168.0.60')
So what pretty much is happening is that when the return value is
"msg": [
[
"logging host 192.168.0.27",
"logging host 192.168.0.60"
]
]
because the 192.168.0.60 is in there it skips the entire task. Can someone help me with a way detect the logging host 192.168.0.27 is in a seperate line of the search?
You'll need to loop over your stdout_lines to check it line by line.
- debug:
msg: "{{ item }}"
when: not "192.168.0.60" in item
with_items: "{{ run.stdout_lines }}"