End play if database does not exits - ansible

I have created the following playbook, to check if a database exists:
- name: Check database exits
shell: |
mysql -hmysqlhost -uroot -ppassword -e "show databases" | egrep db"
register: mysql_exist
- name: Show database
debug:
msg: "{{ mysql_exist.stdout }}"
My idea is to finish the playbook if the database does not exist and show a message, I tried this but it does not work, otherwise I should continue to the next task.
- name: Check database exits
shell: |
mysql -hmysqlhost -uroot -ppassword -e "show databases" | egrep db"
register: mysql_exist
- name: End Playbook If database not exits.
meta: end_play
when: mysql_exist == 0
- name: Show database
debug:
msg: "{{ mysql_exist.stdout }}"
## other tasks
How can I create a playbook to check if a database exists and if it does not exist, it must display the message The database does not exist and finish the playbook without running other tasks?

if you want to show a message if playbook has to finish, use a block:
(you dont show the output of your register when a db doesnt exist so, i suppose your test in when condition is ok!!)
- block:
- name: "end play "
debug:
msg: "db doesnt exist"
- meta: end_play
when: mysql_exist == 0
so the playbook is finished after the message displaying

Do you need to show the message? Stopping the playbook already happens automatically if egrep does not find anything, because it exits with a non-0 code.
Playbook:
---
- hosts: srv1
become: True
tasks:
- name: x
shell: "echo nope | egrep dbname"
- name: good
shell: "echo very much"
Output (notice how "good" is not executed):
PLAY [srv1] *******************************************************************************************************************************
TASK [x] **********************************************************************************************************************************
fatal: [srv1]: FAILED! => {"changed": true, "cmd": "echo nope | egrep dbname", "delta": "0:00:00.005942", "end": "2022-02-09 15:56:56.726828", "msg": "non-zero return code", "rc": 1, "start": "2022-02-09 15:56:56.720886", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
PLAY RECAP ********************************************************************************************************************************
srv1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
It could be approximated with something like this:
- name: x
shell: "echo nope | egrep dbname || { echo Database not found && false; }"
Which gives:
TASK [x] ***********************************************************************************************************************************
fatal: [srv1]: FAILED! => {"changed": true, "cmd": "echo nope | egrep dbname || { echo Database not found && false; }", "delta": "0:00:00.006159", "end": "2022-02-09 15:59:26.176704", "msg": "non-zero return code", "rc": 1, "start": "2022-02-09 15:59:26.170545", "stderr": "", "stderr_lines": [], "stdout": "Database not found", "stdout_lines": ["Database not found"]}

Related

How store output in variable while using the loop in ansible?

I want to check the ip on the server where ip list i have in the json file as below,
cat /tmp/iplist.json
[
"10.10.10.182",
"182.10.10.2",
"192.168.200.2"
]
now the condition is only one ip exist on the system so i was executing the loop to store the only the success output in variable but i am not able to do that does any one knows how can i do this
here is my playbook
---
- name: Load values from json file
hosts: localhost
gather_facts: false
vars:
ip: "{{ lookup('file', '/tmp/iplist.json') | from_json }}"
tasks:
- name: Loop over imported iplist
shell: ip a | grep {{ item }}
loop: "{{ ip }}"
changed_when: true
register: echo
- debug:
msg: "{{ echo }}"
And this how it getting failed error
PLAY [Load values from json file] *************************************************************************************************************************
TASK [Loop over imported iplist] *******************************************************************************************************************************
changed: [localhost] => (item=10.10.10.182)
failed: [localhost] (item=182.10.10.2) => {"ansible_loop_var": "item", "changed": true, "cmd": "ip a | grep 182.10.10.2", "delta": "0:00:00.012178", "end": "2020-05-09 11:30:06.919913", "item": "182.10.10.2", "msg": "non-zero return code", "rc": 1, "start": "2020-05-09 11:30:06.907735", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
failed: [localhost] (item=192.168.200.2) => {"ansible_loop_var": "item", "changed": true, "cmd": "ip a | grep 192.168.200.2", "delta": "0:00:00.029234", "end": "2020-05-09 11:30:07.178768", "item": "192.168.200.2", "msg": "non-zero return code", "rc": 1, "start": "2020-05-09 11:30:07.149534", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
PLAY RECAP *****************************************************************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
When you enable gather_facts: true the variable ansible_all_ipv4_addresses will keep the list of all IPv4 addresses of the host. Use intersect to find common items. For example
- debug:
msg: "{{ ansible_all_ipv4_addresses | intersect(ip) }}"

Ansible Regex: Get a integer from command & pass to other command to run

I have to execute below 2 commands whose value depends on the system.
# sysctl -w kernel.shmmax= parse_from_shm.sh script #For example 17179869184
# sysctl -w kernel.shmall= parse_from_shm.sh script #For example 4194304
./shm.sh will echo both system values required in the below format
kernel.shmmax=4185686016
kernel.shmall=1021896
So I have to parse & get integer value above result & execute ultimately below 2 commands
# sysctl -w kernel.shmmax=4185686016
# sysctl -w kernel.shmall=1021896
I have tried to register & parse the integer values using regex. But I couldn't able to process it perfectly. Any help would be of great help.
---
- hosts: fossology_test
become: true
become_user: root
environment:
HOME: /usr/ansible
gather_facts: no
tasks:
- name: run shell script
become: true
become_user: root
command: ./shm.sh
args:
chdir: /usr/local/src/
register: results
- set_fact:
shmmax: "{{ results.stdout | regex_search(shmmaxregexp, '\\1' ) }}"
shmall: "{{ results.stdout | regex_search(shmallregexp, '\\1' ) }}"
vars:
shmmaxregexp: 'shmmax=([^\"]+)'
shmallregexp: 'shmall=([^\"]+)'
- name: sysctl -w kernel.shmmax="{{ shmmax | int }}"
become: true
become_user: root
command: sysctl -w kernel.shmmax="{{ shmmax | int }}"
- name: sysctl -w kernel.shmall="{{ shmall }}"
become: true
become_user: root
command: sysctl -w kernel.shmall="{{ shmall }}"
This is the output
dinesh#dinesh-VirtualBox:~/Documents/remote/Ansible-Playbook/fossology_playbook$ ansible-playbook regex.yml -K -v
Using /etc/ansible/ansible.cfg as config file
BECOME password:
PLAY [fossology_test] ************************************************************************************
TASK [run shell script] **********************************************************************************
changed: [fossology_test] => {"changed": true, "cmd": ["./shm.sh"], "delta": "0:00:00.005912", "end": "2020-03-28 05:25:42.022156", "rc": 0, "start": "2020-03-28 05:25:42.016244", "stderr": "", "stderr_lines": [], "stdout": "kernel.shmmax=4185686016\nkernel.shmall=1021896", "stdout_lines": ["kernel.shmmax=4185686016", "kernel.shmall=1021896"]}
TASK [set_fact] ******************************************************************************************
ok: [fossology_test] => {"ansible_facts": {"shmall": ["1021896"], "shmmax": ["4185686016\nkernel.shmall=1021896"]}, "changed": false}
TASK [sysctl -w kernel.shmmax="0"] ***********************************************************************
changed: [fossology_test] => {"changed": true, "cmd": ["sysctl", "-w", "kernel.shmmax=0"], "delta": "0:00:00.003133", "end": "2020-03-28 05:25:42.574223", "rc": 0, "start": "2020-03-28 05:25:42.571090", "stderr": "", "stderr_lines": [], "stdout": "kernel.shmmax = 0", "stdout_lines": ["kernel.shmmax = 0"]}
TASK [sysctl -w kernel.shmall="[u'1021896']"] ************************************************************
changed: [fossology_test] => {"changed": true, "cmd": ["sysctl", "-w", "kernel.shmall=[u'1021896']"], "delta": "0:00:00.003558", "end": "2020-03-28 05:25:43.071811", "rc": 0, "start": "2020-03-28 05:25:43.068253", "stderr": "sysctl: setting key \"kernel.shmall\": Invalid argument", "stderr_lines": ["sysctl: setting key \"kernel.shmall\": Invalid argument"], "stdout": "kernel.shmall = [u'1021896']", "stdout_lines": ["kernel.shmall = [u'1021896']"]}
PLAY RECAP ***********************************************************************************************
fossology_test : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I am using ansible 2.9.6
dinesh#dinesh-VirtualBox:/$ ansible --version
ansible 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/dinesh/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.17 (default, Nov 7 2019, 10:07:09) [GCC 7.4.0]
As you can very clearly see in the set_fact results dict, the output of regexp_search is a list of matched strings, not the just the capture group. And, because your regex is imprecise, that's why your shmmax is the numbers plus a newline plus the rest of the text.
The accurate regex is shmmax=([0-9]+) because those values aren't "any character except a double quote" it's "any number after the equals sign"

Ansible single task variable on top of global variable

I have a playbook where I am configuring environment variables for multiple hosts.
these are the global vars set in defaults\main.yml:
environment:
http_proxy: blabla
https_proxy: blabla
Now I have a single task where I need to set another environment variable for the python library.
However, when I set the environment var for that single task it overwrites the global environment vars.
- name: some task
command: command
environment:
ENV_VAR: "blabla"
I want the ENV_VAR for the single task to be added on top of the global vars. But is that even possible?
https://docs.ansible.com/ansible/latest/user_guide/playbooks_environment.html
this page didn't give me anything conclusive.
Could I use the with_items option to achieve this possibly?
The following playbook demonstrates a possible implementation for your requirement using the combine filter associated with default. Run this with -v option to see output of shell commands:
---
- name: Parse several results as json strings
hosts: localhost
gather_facts: false
# This will automatically combine `default_env` (default to empty if it does not exists)
# with `more_env` if this latest var is defined somewhere
environment: "{{ default_env | default({}) | combine(more_env | default({})) }}"
vars:
# Define default environment variables
default_env:
http_proxy: blabla
https_proxy: blabla
tasks:
- name: Show some vars
vars:
# Inject more environment variables for this task
more_env:
toto: titi
shell: |-
echo $http_proxy
echo $https_proxy
echo $toto
- name: Same with default env
shell: |-
echo $http_proxy
echo $https_proxy
echo $toto
Which gives:
$ ansible-playbook test.yml -v
PLAY [Default env override] ****************************************************************************************************************************************************************************************************************************
TASK [Show some vars] ***************************************************************************************************************************************************************************************************************************************************
changed: [localhost] => {"changed": true, "cmd": "echo $http_proxy\necho $https_proxy\necho $toto", "delta": "0:00:00.002207", "end": "2020-01-07 09:57:30.178989", "rc": 0, "start": "2020-01-07 09:57:30.176782", "stderr": "", "stderr_lines": [], "stdout": "blabla\nblabla\ntiti", "stdout_lines": ["blabla", "blabla", "titi"]}
TASK [Same with default env] ********************************************************************************************************************************************************************************************************************************************
changed: [localhost] => {"changed": true, "cmd": "echo $http_proxy\necho $https_proxy\necho $toto", "delta": "0:00:00.001875", "end": "2020-01-07 09:57:30.626163", "rc": 0, "start": "2020-01-07 09:57:30.624288", "stderr": "", "stderr_lines": [], "stdout": "blabla\nblabla", "stdout_lines": ["blabla", "blabla"]}
PLAY RECAP **************************************************************************************************************************************************************************************************************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

how to extract string from ansible regsiter variable in ansible

I have written the following ansible playbook to find the disk failure on the raid
- name: checking raid status
shell: "cat /proc/mdstat | grep nvme"
register: "array_check"
- debug:
msg: "{{ array_check.stdout_lines }}"
Following is the output I got
"msg": [
"md0 : active raid1 nvme0n1p1[0] nvme1n1p1[1]",
"md2 : active raid1 nvme1n1p3[1](F) nvme0n1p3[0]",
"md1 : active raid1 nvme1n1p2[1] nvme0n1p2[0]"
]
I want to extract the disk name which is failed from the register variable array_check.
How do I do this in the ansible? Can I use set_fact module in ansible? Can I use grep, awk, sed command on the register variable array_check
This is the playbook I am using to check the health status of a drive using smartctl
- name: checking the smartctl logs
shell: "smartctl -H /dev/{{ item }}"
with_items:
- nvme0
- nvme1
And I am facing the following error
(item=nvme0) => {"changed": true, "cmd": "smartctl -H /dev/nvme0", "delta": "0:00:00.090760", "end": "2019-09-05 11:21:17.035173", "failed": true, "item": "nvme0", "rc": 127, "start": "2019-09-05 11:21:16.944413", "stderr": "/bin/sh: 1: smartctl: not found", "stdout": "", "stdout_lines": [], "warnings": []}
(item=nvme1) => {"changed": true, "cmd": "smartctl -H /dev/nvme1", "delta": "0:00:00.086596", "end": "2019-09-05 11:21:17.654036", "failed": true, "item": "nvme1", "rc": 127, "start": "2019-09-05 11:21:17.567440", "stderr": "/bin/sh: 1: smartctl: not found", "stdout": "", "stdout_lines": [], "warnings": []}
The desired output should be something like this,
=== START OF SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
Below is the complete playbook including the logic to execute multiple commands in a single task using with_items,
---
- hosts: raid_host
remote_user: ansible
become: yes
become_method: sudo
tasks:
- name: checking raid status
shell: "cat /proc/mdstat | grep 'F' | cut -d' ' -f6 | cut -d'[' -f1"
register: "array_check"
- debug:
msg: "{{ array_check.stdout_lines }}"
- name: checking the samrtctl logs for the drive
shell: "/usr/sbin/smartctl -H /dev/{{ item }} | tail -2|awk -F' ' '{print $6}'"
with_items:
- "nvme0"
- "nvme1"
register: "smartctl_status"

Automate User Password Change using Ansible Playbook

I would like to change a user password if it exists, but I get this error
here my code
- name: Check for foo user
with_items: foo
changed_when: false
command: grep {{ item }} -q /etc/passwd
register: find_user
- name: Update foo user's Password
user:
name: foo
update_password: always
password: $6$rounds=656000$ZjMwlMPWqwGKF1nY$JbarjwHGtlr5PD3Yqfb5phz18gnHujSgmpD29DxsXQ7a7UdhuO
when: find_user is changed
TASK [Check for foo user] *****************************************************************************************************************************************************************************************
fatal: [192.168.56.124]: FAILED! => {"changed": false, "cmd": "grep -w 'foo' /etc/passwd", "delta": "0:00:00.003024", "end": "2019-07-01 12:59:45.966160", "msg": "non-zero return code", "rc": 1, "start": "2019-07-01 12:59:45.963136", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
Use getent module to test the existence of the user.
- name: Read passwd
getent:
database: passwd
- name: Update foo users password
user:
name: foo
update_password: always
password: ...
when: "'foo' in getent_passwd"
That's because the command task you have is having an exit code = 1 when the username does not exist in the /etc/passwd file:
[http_offline#greenhat-29 tests]$ grep foo -q /etc/passwd
[http_offline#greenhat-29 tests]$ echo $?
1
[http_offline#greenhat-29 tests]$ grep root -q /etc/passwd
[http_offline#greenhat-29 tests]$ echo $?
0
[http_offline#greenhat-29 tests]$
What you can do, is instruct this task to NOT fail when exit code from the grep command is not 0 or 1. To do that you need to add this clause in the command task:
failed_when: find_user.rc !=0 and find_user.rc !=1
The whole task would look like:
- name: Check for foo user
with_items: foo
changed_when: false
command: grep {{ item }} -q /etc/passwd
register: find_user
failed_when: find_user.rc !=0 and find_user.rc !=1

Resources