Ansible task - Evaluate when with or and - ansible

I have vars like this:
vars:
src_wls: "{{ source_database.src_wls_password }}"
src_pwd: "{{ source_database.src_password }}"
tgt_secondary_servers: "{{ inventory_hostname }}"
I want it to run this part if the env is 003 or 004 and the secondary server is like *app02*
I've tried a few iterations, but can't get it to work. Thanks for looking.
- name: Performing managed server
shell: "cd {{ dest }}; {{ dest }}/script_app.sh {{ src_pwd }} {{ src_wls }}"
when:
- target_clone == '003' or target_clone == '004'
- tgt_secondary_servers | regex_search("*app02")
fatal: [lebapp02]: FAILED! => {"msg": "The conditional check 'tgt_secondary_servers | regex_search("*app02")' failed. The error was: nothing to repeat\n\nThe error appears to be in 'main.yml': line 27, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Performing managed server)\n ^ here\n"}
expecting it to run on 003 or 004 if server is like *app02

As a start, 2 enhancements that are not the source of your error:
your first condition can be simplified for performance, readability and scalability by checking for the presence of a value in a list with the in test rather than making all tests one after the other.
you're not using default values in case your vars are undefined which can lead to more errors when running (i.e. variable xxxx is undefined)
Your real problem is the second condition which:
is applying a filter returning a string rather than making a boolean test (e.g. is <some_test>, == 'some_value', ...)
receives as a parameter something that is not a regex (or at least not the one you seem to be looking for)
Since you're just looking for a substring, the most straightforward way is to use search.
Here is a fixed version:
when:
- target_clone | d('') in ['003', '004']
- tgt_secondary_servers | d('') is search('app02')
References:
ansible tests
ansible filters

Related

Ansible regex_findall is not giving expected results with negative search

My ansible negative regex is returning everything
So I'm getting results of dns names from JSON, of which I'm trying to sort to create an automated ansible inventory.
I have servers with naming schemes such as:
abc02vsomeserver01.subdomain1.domain.gov
abc02someserver01.subdomain1.domain.gov
xyz03votherserver11.subdomain2.domain.gov
wyz03otherserver11.subdomain2.domain.gov
qrsmainserver02.maindomain.domain.gov
I'm getting the "v" servers divided out by environment, then I want to create a catchall group that is not the "v" servers
So! I'm attempting to do:
{{ jsonOutput | json_query('json.response.results[].dnsName') | regex_findall('(?![a-z]{3}[0-9]{2}v)^.*', multiline=true) }}
Which does seem to work when I plug it into https://pythex.org.
But ansible is returning everything instead...
What the heck am I doing wrong here?
It's because that json_query emits a list[str] which when fed directly into regex_findall doesn't become a newline delimited string, it becomes the same as str(["alpha", "beta"]) (e.g. ['alpha', 'beta']) and then the multiline regex fails to do what you are expecting
There are, as with many things in life, a few ways to fix that. One is to just feed the results into |join("\n") and then you're likely back where you thought you were to begin with:
- debug:
msg: "{{ jsonOutput | json_query('json.response.results[].dnsName') | join('\n') | regex_findall('(?![a-z]{3}[0-9]{2}v)^.*', multiline=true) }}"
The other is to acknowledge that it's a list[str] and use the | select("match", ...) filter to only allow though items that match:
- debug:
msg: >-
{{ response | json_query('results[].dnsName')
| select('match', '(?![a-z]{3}[0-9]{2}v)^.*')
| list }}
vars:
response:
results:
- dnsName: abc02vsomeserver01.subdomain1.domain.gov
- dnsName: abc02someserver01.subdomain1.domain.gov
- dnsName: xyz03votherserver11.subdomain2.domain.gov
- dnsName: wyz03otherserver11.subdomain2.domain.gov
- dnsName: qrsmainserver02.maindomain.domain.gov
similarly produces:
"msg": [
"abc02someserver01.subdomain1.domain.gov",
"wyz03otherserver11.subdomain2.domain.gov",
"qrsmainserver02.maindomain.domain.gov"
]
I would guess it's personal preference which style works best in your playbook

Using Jinja filter with two variables in Ansible

I am trying to get a random host in a group that contains a list of IP's. We are running into some issues as our group name uses a variable, but the line is already in {{'s due to the Jinja random call.
- hosts: "{{ {{ env }}_as_group | random }}"
ERROR! template error while templating string: expected token 'end of print statement', got '{'. String: {{ {{ env }}_as_group | random }}
The env variable is passed into the playbook on execution with ansible-playbook "-e env=stage" myplaybook.yml
Looking around online, most people solve this with vars[env], however that doesnt seem to quite work for us -
- hosts: "{{ vars[env]_as_group | random }}"
ERROR! template error while templating string: expected token 'end of print statement', got '_as_group'. String: {{ tag_aws_autoscaling_groupName_[ env ]_as_group | random }}
If I make it - hosts: "{{ stage_as_group | random }}", it works as expected.
How can I set the host to pull a random value in the group {{ env }}_as_group?
In Ansible, moustache should not be stacked.
So you should use the proper Jinja concatenation operator: ~.
Ending with:
- hosts: "{{ vars[env ~ '_as_group'] | random }}"
This said it is not totally clear to me what stage_as_group really is: is it a list or a hosts group?
If this is a group in you inventory, this won't work because random works on a sequence, and a host group is a string, not a sequence.
For that use case, you probably want this instead:
- hosts: "{{ groups[env ~ '_as_group'] | random }}"

I have used register variable to store output values of task so i'm using same value in when condition from ansible role

---
- name: Check the apps list in ArgoCD server with related to cluster:"{{clustername.stdout}}"
shell: |
argocd app list | grep {{clusterip.stdout}} | grep {{proj_name}} | awk '{print $1}'
register: applist
- debug:
var: applist.stdout_lines
- name: Create xedge apps to production ns
shell: |
argocd app create {{item}}-{{app_extention}} --project {{proj_name}} --repo {{gitops_url}} --revision HEAD --values {{values_file}}.yaml --path {{item}} --dest-namespace production --label app={{item}} --dest-server {{clusterip.stdout}}
with_items:
- "{{production_apps}}"
#skip apps creation if apps are already existed
when : "item-app_extention not in applist.stdout_lines"
''
error:
fatal: [localhost]: FAILED! => {"msg": "The conditional check 'item-app_extention not in applist.stdout_lines' failed. The error was: Unexpected templating type error occurred on ({% if item-app_extention not in applist.stdout_lines %} True {% else %} False {% endif %}): unsupported operand type(s) for -: 'AnsibleUnsafeText' and 'AnsibleUnicode'\n\nThe error appears to be in '/etc/ansible/roles/xedge/tasks/argocd_apps.yml': line 8, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n var: applist.stdout_lines\n- name: Create xedge apps to production ns\n ^ here\n"}
''
You're trying to perform substration on string values, here:
with_items:
- "{{production_apps}}"
#skip apps creation if apps are already existed
when : "item-app_extention not in applist.stdout_lines"
An unquoted variable name is a variable reference. You're try to subtract app_extention from item. I think you mean something like:
when: "item ~ '-' ~ app_extention not in applist.stdout_lines
Where ~ is the string concatenation operator.
Or with less confusing quoting, using the > folding block operator so we're not nesting quotes:
when: >
item ~ '-' ~ app_extention not in applist.stdout_lines
Or using string formatting rather than concatenation:
when: >
'%s-%s' % (item, app_extention) not in applist.stdout_lines

Using when conditional to match string in output register (Ansible)

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).

Ansible Print IOS output on string match

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/")

Resources