Search for a regular expression in a file in Ansible - bash

I am trying to convert a small bash code snippet to Ansible but I am finding it hard to implement. Basically, it is first checking if /etc/redhat-release exists. If yes, it is looking for a regex pattern *release 6.8*. If the pattern is found, then it is checking for another file /bin/login.ori. If it exists, then it performs a couple of operations.
#fixed RHEL6.8/CentOS6.8 rlogin issue
if [ -f /etc/redhat-release ]; then
case `cat /etc/redhat-release` in
*'release 6.8'*)
if [ ! -e /bin/login.ori ]; then
cp -f
/bin/login /bin/login.ori
cp -f $MDIR/login.bin.68 /bin/login
restorecon /bin/login
fi
;;
esac
fi
Here is what I have tried so far:
- name: Fix RHEL6.8/CentOS6.8 rlogin issue
stat:
path: /etc/redhat-release
register: redhat_file
- debug:
msg: "File exists: {{ redhat_file }}"
when: redhat_file.stat.exists
- name: Check whether /etc/redhat-release contains "*release 6.8*"
lineinfile:
path: /etc/redhat-release
line: '*release 7.3*'
# insertafter: [main]
register: checkmyconf
when: redhat_file.stat.exists
- name: Greet the world if /etc/redhat-release contains "*release 6.8*"
debug:
msg: "{{ checkmyconf }}"
when: checkmyconf.stdout | match('*release 7.3.1611*')
But I am getting below error. Kindly help.
TASK [qsc/hack/v1 : Check whether /etc/redhat-release contains "*release 6.8*"] *******************************************************
ok: [ansible-poc-cos6]
ok: [ansible-poc-rhel6]
ok: [ansible-poc-centos7]
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|match` use `result is match`. This feature will
be removed in version 2.9. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
TASK [qsc/hack/v1 : Greet the world if /etc/redhat-release contains "*release 6.8*"] **************************************************
fatal: [ansible-poc-cos6]: FAILED! => {"msg": "The conditional check 'checkmyconf.stdout | match('*release 7.3.1611*')' failed. The error was: nothing to repeat\n\nThe error appears to have been in '/remote/us01home53/subburat/snps-ansible/roles/qsc/hack/v1/tasks/main.yml': line 31, 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 - name: Greet the world if /etc/redhat-release contains \"*release 6.8*\"\n ^ here\n"}
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|match` use `result is match`. This feature will
be removed in version 2.9. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
fatal: [ansible-poc-rhel6]: FAILED! => {"msg": "The conditional check 'checkmyconf.stdout | match('*release 7.3.1611*')' failed. The error was: nothing to repeat\n\nThe error appears to have been in '/remote/us01home53/subburat/snps-ansible/roles/qsc/hack/v1/tasks/main.yml': line 31, 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 - name: Greet the world if /etc/redhat-release contains \"*release 6.8*\"\n ^ here\n"}
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|match` use `result is match`. This feature will
be removed in version 2.9. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
fatal: [ansible-poc-centos7]: FAILED! => {"msg": "The conditional check 'checkmyconf.stdout | match('*release 7.3.1611*')' failed. The error was: nothing to repeat\n\nThe error appears to have been in '/remote/us01home53/subburat/snps-ansible/roles/qsc/hack/v1/tasks/main.yml': line 31, 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 - name: Greet the world if /etc/redhat-release contains \"*release 6.8*\"\n ^ here\n"}
to retry, use: --limit #/remote/us01home53/subburat/snps-ansible/push-full.retry
PLAY RECAP ****************************************************************************************************************************
ansible-poc-centos7 : ok=3 changed=0 unreachable=0 failed=1
ansible-poc-cos6 : ok=3 changed=0 unreachable=0 failed=1
ansible-poc-rhel6 : ok=3 changed=0 unreachable=0 failed=1
Note: I have tried all the suggestions in this link but it does not work for this use-case as the line attribute in my use-case is dynamic.

This is the equivalent
- stat:
path: /bin/login.ori
register: result
- block:
- copy:
src: /bin/login
dest: /bin/login.ori
remote_src: true
- copy:
src: "{{ ansible_env.MDIR }}/login.bin.68"
dest: /bin/login
remote_src: true
force: true
- command: restorecon /bin/login
when:
- ansible_distribution == 'Red Hat Enterprise Linux'
- ansible_distribution_version == '6.8'
- not result.stat.exists|bool
(not tested)
Notes
gather_facts must be enabled to collect ansible_* variables.
It's not necessary to "force" the first copy because the "dest" does not exist.
I'm not sure if the requirement to fix both "RHEL6.8/CentOS6.8" and testing the existence of "/etc/redhat-release" only is consistent (I have no access to 6.8 atm). Fit the conditions in the block to your needs.

Related

Ansible Handler and when condition

I am trying to find a logic to check if the service is running, if Not Running, then start it. Below is the logic I have written, but for some reason the notify is not calling the handler?
---
- name: Executing the play to start the service
hosts: nodes
become: yes
gather_facts: False
tasks:
- name: Executing the Shell task to check the status of the wso2 instance
shell: myMsg=$(sudo service wso2esb status| grep Active | awk '{print $3}');if [[ $myMsg == "(dead)" ]]; then echo "Not Running";else echo "Running";fi
ignore_errors: yes
register: result
notify: handl
when: result.stdout == "Not Running" (I even tried 'changed_when', but the same error)
handlers:
- name: handl
service: name=wso2esb state=started
$ ansible-playbook -i inventories/hosts.sit start.yml -b -k
SSH password:
PLAY [Executing the play to start the wso2 service] ***********************************************
TASK [Executing the Shell task to check the status of the instance] *******************************
fatal: [mpstest01]: FAILED! => {"msg": "The conditional check 'result.stdout == \"Not Running\"' failed. The error was: error while evaluating conditional (result.stdout == \"Not Running\"): **'result' is undefined**\n\nThe error appears to have been in '/home/ansible1/start.yml': line 9, 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 - name: Executing the Shell task to check the status of the instance\n ^ here\n"}
...ignoring
PLAY RECAP ****************************************************************************************
mpstest01 : ok=1 changed=0 unreachable=0 failed=0
That all seems unnecessary. You don't need to "check if the service is running, if Not Running, then start it"; that's exactly what the service module does. Just put the service module in a task, and don't bother with the handler:
- name: start service if it isn't already running
service: name=wso2esb state=started
Although I would prefer YAML syntax rather than the key=value syntax:
- name: start service if it isn't already running
service:
name: wso2esb
state: started
In any case, the service module will check if the service is running, and if not, it will start it.

Unable to search output of Cisco show command using Ansible

Running Ansible 2.7.4
I have the following code:
- hosts: switches
tasks:
- name: show run on remote devices
ios_command:
commands: show run
register: output
- name: Display The Results
debug:
msg: "Enable Secret Found"
when: ('secret' in output.stdout)
I want to read in the output of a show run command on a Cisco switch and then search that output for specific phrases in the output.
If a match is found I want a message to be displayed to the screen, however no match is ever found.
PLAY [switches] *****************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [10.10.2.68]
TASK [show run on remote devices] ***********************************************************************************************************************************************************************************************************
ok: [10.10.2.68]
TASK [Display The Results] ******************************************************************************************************************************************************************************************************************
skipping: [10.10.2.68]
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.10.2.68 : ok=2 changed=0 unreachable=0 failed=0
I have also tried altering the when statement to
when: output.stdout.find('enable') != -1
but this gives me the following error:
fatal: [10.10.2.68]: FAILED! => {"msg": "The conditional check 'output.stdout.find('enable') != -1' failed. The error was: error while evaluating conditional (output.stdout.find('enable') != -1): 'list object' has no attribute 'find'\n\nThe error appears to have been in '/etc/ansible/playbooks/showrun2.yml': line 8, 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 - name: Display The Results\n ^ here\n"}
Any idea what I'm doing wrong?
'list object' has no attribute 'find'
I'm not sure how much clearer you would expect the error message to be, but in that circumstance output.stdout is a list, not a str
So you'll want
"enable" in (output.stdout | join("\n"))
or the strictly pythonic way
"enable" in "\n".join(output.stdout)

Ansible when statement with variable from another task

can someone help me please?
I want to create a folder at host "cfme_tester-0".
For this I check variable "osp_version" from "undercloud-0" host and based on the result I should create a folder at the "cfme_tester-0" host.
Here is my playbook:
- name: take openstack version
hosts: undercloud-0
become: true
become_user: stack
tasks:
- name: creating flavor
shell: |
source /home/stack/stackrc
cat /etc/rhosp-release | egrep -o '[0-9]+' | head -1
register: osp_version
ignore_errors: True
- debug: msg="{{ osp_version.stdout }}"
- name: set up CFME tester
hosts: cfme_tester-0
become: yes
become_user: root
tasks:
- name: Run prepare script for OSP10
debug:
shell: |
cd /tmp/cfme/ && mkdir osp10
when: "'10' in osp_version.stdout"
- name: Run prepare script for OSP13
debug:
shell: |
cd /tmp/cfme/ && mkdir osp13
when: "'13' in osp_version.stdout"
But an error occurs:
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [undercloud-0] => {
"msg": "10"
}
PLAY [set up CFME tester] *****************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [cfme_tester-0]
TASK [Run prepare script for OSP10] *******************************************************************************************************************************************************************************
fatal: [cfme_tester-0]: FAILED! => {"msg": "The conditional check ''10' in osp_version.stdout' failed. The error was: error while evaluating conditional ('10' in osp_version.stdout): 'osp_version' is undefined\n\nThe error appears to have been in '/root/infrared/rhos-qe-core-installer/playbooks/my_setup.yaml': line 20, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Run prepare script for OSP10\n ^ here\n"}
to retry, use: --limit #/root/infrared/rhos-qe-core-installer/playbooks/my_setup.retry
PLAY RECAP ********************************************************************************************************************************************************************************************************
cfme_tester-0 : ok=1 changed=0 unreachable=0 failed=1
undercloud-0 : ok=3 changed=1 unreachable=0 failed=0
Variables are per-host (because otherwise, what happens when you run a task on multiple hosts and register a variable?). In your first task, you are setting the osp_version variable for host undercloud-0.
If you want to use this variable in your second play, which is running on cfme_tester-0, then you should read the Magic Variables, and How To Access Information About Other Hosts section of the Ansible documentation. You'll need to refer to the variable via the hostvars dictionary, so your second play will look like:
- name: set up CFME tester
hosts: cfme_tester-0
become: yes
become_user: root
tasks:
- name: Run prepare script for OSP10
shell: |
cd /tmp/cfme/ && mkdir osp10
when: "'10' in hostvars['undercloud-0'].osp_version.stdout"
- name: Run prepare script for OSP13
shell: |
cd /tmp/cfme/ && mkdir osp13
when: "'13' in hostvars['undercloud-0'].osp_version.stdout"
...but note that if you're just creating a directory, you would be better off just using the file module instead:
- name: Run prepare script for OSP10
file:
path: /tmp/cfme/osp10
state: directory
when: "'10' in hostvars['undercloud-0'].osp_version.stdout"

Ansible fails to locate templates in role's /templates directory [duplicate]

Does ansible pass Role Default variables to the Handlers within the same Role?
Here's a minimal excerpt of the playbook that has the issue:
Role hierarchy
- playbook.yml
- roles/
- gunicorn/
- defaults/
- main.yml
- handlers/
- main.yml
- code-checkout/
- tasks/
- main.yml
Here's the file contents
gunicorn/defaults/main.yml
---
gu_log: "/tmp/gunicorn.log"
gunicorn/handlers/main.yml
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
finalize/tasks/main.yml
---
- name: Test Handlers
shell: ls
notify:
- Restart Gunicorn
playbook.yml
---
- name: Deploy
hosts: webservers
tasks:
- include: roles/finalize/tasks/main.yml
handlers:
- include: roles/gunicorn/handlers/main.yml
AFAIK everything looks good. However, I get this error during the playbook execution
FAILED! => {"failed": true, "msg": "the field 'args' has an invalid
value, which appears to include a variable that is undefined. The
error was: 'gu_log' is undefined\n\nThe error appears to have been in
'/roles/gunicorn/handlers/main.yml':
line 3, 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: Restart Gunicorn\n ^ here\n"}
Using Ansible 2.2 on Ubuntu 12.04 LTS
Here's a modified version of techraf's script that creates all the directories and demonstrates my issue
#!/bin/bash
mkdir -p ./rtindru-test/roles/gunicorn
mkdir -p ./rtindru-test/roles/gunicorn/defaults
mkdir -p ./rtindru-test/roles/gunicorn/handlers
mkdir -p ./rtindru-test/roles/finalize/tasks
cat >./rtindru-test/roles/finalize/tasks/main.yml <<HANDLERS_END
---
- name: Test Handlers
shell: rm {{ gu_log }}
HANDLERS_END
cat >./rtindru-test/roles/gunicorn/handlers/main.yml <<HANDLERS_END
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
HANDLERS_END
cat >./rtindru-test/roles/gunicorn/defaults/main.yml <<DEFAULTS_END
---
gu_log: "/tmp/gunicorn.log"
DEFAULTS_END
cat >./rtindru-test/playbook.yml <<PLAYBOOK_END
---
- name: Deploy
hosts: localhost
tasks:
- include: roles/finalize/tasks/main.yml
handlers:
- include: roles/gunicorn/handlers/main.yml
PLAYBOOK_END
touch /tmp/gunicorn.log
ls -l /tmp/gunicorn.log
ansible-playbook ./rtindru-test/playbook.yml
ls -l /tmp/gunicorn.log
Output
PLAY [Deploy]
TASK [setup]
******************************************************************* ok: [localhost]
TASK [Test Handlers]
*********************************************************** fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has
an invalid value, which appears to include a variable that is
undefined. The error was: 'gu_log' is undefined\n\nThe error appears
to have been in '/rtindru-test/roles/finalize/tasks/main.yml': line 2,
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:
Test Handlers\n ^ here\n"} to retry, use: --limit
#/rtindru-test/playbook.retry
PLAY RECAP
********************************************************************* localhost : ok=1 changed=0 unreachable=0
failed=1
You are neither defining nor using any roles. With the following task:
- include: roles/finalize/tasks/main.yml
you are only including a tasks file into your playbook. It has nothing to do with roles.
To assign a role you should specify a list of roles for a play (one or more):
role:
- my_role1
- my_role2
Please have a look at the documentation on roles and feel free to use the playbook and structure as created by the below script.
Does ansible pass Role Default variables to the Handlers within the same Role?
Yes it does.
For a proof run the following bash script which creates and runs a minimal example. It takes the contents of gunicorn/defaults/main.yml and gunicorn/handlers/main.yml from the question intact and adds missing components: the tasks and the playbook. It creates a file to be removed and runs the playbook.
#!/bin/bash
mkdir -p ./so41285033/roles/gunicorn
mkdir -p ./so41285033/roles/gunicorn/defaults
mkdir -p ./so41285033/roles/gunicorn/handlers
mkdir -p ./so41285033/roles/gunicorn/tasks
cat >./so41285033/roles/gunicorn/tasks/main.yml <<TASKS_END
---
- debug:
changed_when: true
notify: Clear Gunicorn Log
TASKS_END
cat >./so41285033/roles/gunicorn/handlers/main.yml <<HANDLERS_END
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
when: "'apiservers' not in group_names"
HANDLERS_END
cat >./so41285033/roles/gunicorn/defaults/main.yml <<DEFAULTS_END
---
gu_log: "/tmp/gunicorn.log"
DEFAULTS_END
cat >./so41285033/playbook.yml <<PLAYBOOK_END
---
- hosts: localhost
gather_facts: no
connection: local
roles:
- gunicorn
PLAYBOOK_END
touch /tmp/gunicorn.log
ls -l /tmp/gunicorn.log
ansible-playbook ./so41285033/playbook.yml
ls -l /tmp/gunicorn.log
The result:
-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log
[WARNING]: Host file not found: /etc/ansible/hosts
[WARNING]: provided hosts list is empty, only localhost is available
PLAY [localhost] ***************************************************************
TASK [gunicorn : debug] ********************************************************
ok: [localhost] => {
"msg": "Hello world!"
}
RUNNING HANDLER [gunicorn : Clear Gunicorn Log] ********************************
changed: [localhost]
[WARNING]: Consider using file module with state=absent rather than running rm
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0
ls: /tmp/gunicorn.log: No such file or directory
Interpretation:
Before running the playbook the file /tmp/gunicorn.log was created and its existence verified:
-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log
After running the playbook the file /tmp/gunicorn.log does not exist:
ls: /tmp/gunicorn.log: No such file or directory
Ansible correctly passed the variable gu_log value to the Clear Gunicorn Log handler which removed the file.
Final remark:
The problem described in question is impossible to reproduce, because the question does not contain complete nor verifiable example in the meaning of MCVE.

How should an include playbook be different from a standalone one?

I have two playbooks which are launched against a remote host (10.233.84.58). When launched standalone (ansible-playbook -i inventory.txt playbook.yml) they work fine.
The first playbook includes the second one, which is identical, except obviously for the include:
---
- hosts: all
tasks:
- debug: msg="hello form playbook1"
# up to now the content is identical between playbook1.yaml and playbook2.yaml
# without the next line the playbook runs fine
- include: playbook2.yml
When I run playbook1.yml:
# ansible-playbook -i inventory.txt playbook1.yml (masterāœ±)
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
ok: [10.233.84.58]
TASK [debug] *******************************************************************
ok: [10.233.84.58] => {
"msg": "hello form playbook1"
}
TASK [include] *****************************************************************
fatal: [10.233.84.58]: FAILED! => {"failed": true, "reason": "no action detected in task. This often indicates a misspelled module name, or incorrect module path.\n\nThe error appears to have been in '/root/tests/playbook2.yml': line 2, 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- hosts: all\n ^ here\n\n\nThe error appears to have been in '/root/tests/playbook2.yml': line 2, 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- hosts: all\n ^ here\n"}
NO MORE HOSTS LEFT *************************************************************
to retry, use: --limit #playbook1.retry
PLAY RECAP *********************************************************************
10.233.84.58 : ok=2 changed=0 unreachable=0 failed=1
I extracted the "reason" from the error message above and made it more readable:
no action detected in task. This often indicates a misspelled module name, or incorrect module path.
The error appears to have been in '/root/tests/playbook2.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
---
- hosts: all
^ here
How should an include playbook be different from a standalone one?
There are two types of include. You can include playbook or list of tasks.
---
- hosts: all
tasks:
- include: list_of_tasks.yml
- include: complete_playbook.yml
In your example you try to include playbook2.yml as a list of tasks.
Move include on the same indent as - hosts and you'll be good.

Resources