Senario:
1. I need to run two plays in a single playbook.
2. The second play should run after the first play.
3. The first play create few instance and update the inventory file by making new group.
4. Second play uses the updated group and install few packages.
Problem: If I am running both plays separately it is success.
But, i need them in same scripts.
The problem i think is both play executing in parallel.
And thanks in advance.
---
- name: ec2
hosts: localhost
connection: local
roles:
- launchEc2
- hosts: ansible
gather_facts: Fasle
become: yes
roles:
- python
OUTPUT:
PLAY [ec2] *********************************************************************
TASK [setup] *******************************************************************
ok: [127.0.0.1]
TASK [launchEc2 : include_vars] ************************************************
ok: [127.0.0.1]
TASK [launchEc2 : Launch new ec2 instance] *************************************
changed: [127.0.0.1]
TASK [launchEc2 : Add ec2 ip to the hostgroup] *********************************
changed: [127.0.0.1] => (item={.....})
TASK [launchEc2 : wait for SSh to come up] *************************************
ok: [127.0.0.1] => (item={.....})
PLAY [ansible] *****************************************************************
TASK [python : install python] *************************************************
skipping: [34.203.228.19]
PLAY RECAP *********************************************************************
127.0.0.1 : ok=5 changed=2 unreachable=0 failed=0
34.203.228.19 : ok=0 changed=0 unreachable=0 failed=0
Ansible loads inventory before processing playbook.
In your case the second play has the same inventory as it was before modification in the first play.
Generally when you provision cloud hosts you may want to use add_host to dynamically add new hosts to in memory inventory, so they are available to subsequent plays.
You may also try to call meta: refresh_inventory after your inventory modification, but I'm not sure wether it work with updating static inventory.
Related
I am trying to understand --become in order to use ansible to do some local task on my centos. I tried several ansible modules (copy, unarchive) with become that each result with diffetent kind of errors.
Platform used: centos 7
Ansible (installed in a python 3 virtual env) version:
(ansible) [maadam#linux update_centos]$ ansible --version
ansible 2.10.16
config file = None
configured module search path = ['/home/maadam/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/maadam/Sources/python/venv/ansible/lib64/python3.6/site-packages/ansible
executable location = /home/maadam/Sources/python/venv/ansible/bin/ansible
python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
I tried to reproduice the example provided by #techraf in this issue to test become: Using --become for ansible_connection=local.
I used the same playbook:
---
- hosts: localhost
gather_facts: no
connection: local
tasks:
- command: whoami
register: whoami
- debug:
var: whoami.stdout
So I hope the same result as this:
(ansible) [maadam#linux update_centos]$ sudo whoami
root
Whithout become:
ansible) [maadam#linux update_centos]$ ansible-playbook playbook.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost
does not match 'all'
PLAY [localhost] ***************************************************************************************
TASK [command] *****************************************************************************************
changed: [localhost]
TASK [debug] *******************************************************************************************
ok: [localhost] => {
"whoami.stdout": "maadam"
}
PLAY RECAP *********************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
With become I have this error:
(ansible) [maadam#linux update_centos]$ ansible-playbook playbook.yml --become
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost
does not match 'all'
PLAY [localhost] ***************************************************************************************
TASK [command] *****************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "/var/tmp/sclPip796: line 8: -H: command not found\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 127}
PLAY RECAP *********************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
So I don't understand what I am missing with become.
Thanks for your helps
in ansible.cfg file check for the become_method. you can use "sudo su -".
I don't know if I handle this correctly but if I run my playbook as root, I have no error:
(ansible) [maadam#linux update_centos]$ sudo ansible-playbook playbook.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [command] ****************************************************************************************************************************************************************************************************
changed: [localhost]
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [localhost] => {
"whoami.stdout": "root"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Not sure it is the right way to doing things in local with ansible. Sure if you are already root, no need for privilege escalation.
I'm trying to run an ansible playbook against multiple hosts that are running containers using the same name. There are 3 hosts each running a container called "web". I'm trying to use the docker connection.
I'm using the typical pattern of a hosts file which works fine for running ansible modules on the host.
- name: Ping
ping:
- name: Add web container to inventory
add_host:
name: web
ansible_connection: docker
ansible_docker_extra_args: "-H=tcp://{{ ansible_host }}:2375"
ansible_user: root
changed_when: false
- name: Remove old logging directory
delegate_to: web
file:
state: absent
path: /var/log/old_logs
It only works against the first host in the hosts file
PLAY [all]
TASK [Gathering Facts]
ok: [web1]
ok: [web2]
ok: [web3]
TASK [web-playbook : Ping]
ok: [web1]
ok: [web2]
ok: [web3]
TASK [web-playbook : Add sensor container to inventory]
ok: [web1]
PLAY RECAP
web1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web3 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I've tried setting name to web_{{ ansible_host }} to make it unique between hosts but it then tries to connect to web_web1. I've been running the commands using sudo docker exec web rm -rf /var/log/old_logs which of course works, but I'd like to be able to use the ansible modules directly in the docker containers.
The result you get is absolutely expected. Quoting the add_host documentation
This module bypasses the play host loop and only runs once for all the hosts in the play, if you need it to iterate use a with-loop construct.
i.e. you cannot rely on the hosts loop for the add_host and need to make a loop yourself.
Moreover, you definitely need to have different names (i.e. inventory_hostname) for your dynamically created hosts but since all your docker containers have the same name, their ansible_host should be the same.
Assuming all your docker host machines are in the group dockerhosts, the following playbook should do the job. I'm currently not in a situation where I can test this myself so you may have to adjust a bit. Let me know if it helped you and if I have to edit my answer.
Note that even though the add_host task will not naturally loop, I kept the hosts on your original group in the first play so that facts are gathered correctly and correctly populated in the hostvars magic variable
---
- name: Create dynamic inventory for docker containers
hosts: dockerhosts
tasks:
- name: Add web container to inventory
add_host:
name: "web_{{ item }}"
groups:
- dockercontainers
ansible_connection: docker
ansible_host: web
ansible_docker_extra_args: "-H=tcp://{{ hostvars[item].ansible_host }}:2375"
ansible_user: root
loop: "{{ groups['dockerhosts'] }}"
- name: Play needed commands on containers
hosts: dockercontainers
tasks:
- name: Remove old logging directory
file:
state: absent
path: /var/log/old_logs
Setup
I have several roles which declare role dependencies and sometimes use handlers from roles they depend on. A simplified version of my setup looks like this (This is the output of head inventory **/*.yml and it shows all path names and the full contents of the files):
==> inventory <==
[app]
server1 ansible_host=192.168.2.113
[db]
server2 ansible_host=192.168.2.153
==> playbook.yml <==
- hosts: all
roles:
- { role: app, when: "inventory_hostname in groups['app']" }
- { role: db, when: "inventory_hostname in groups['db']" }
==> roles/app/handlers/main.yml <==
- name: app handler
command: echo app handler
==> roles/app/meta/main.yml <==
dependencies: [base]
==> roles/app/tasks/main.yml <==
- command: /bin/true
notify: [app handler, base handler]
==> roles/base/handlers/main.yml <==
- name: base handler
command: echo base handler
==> roles/base/tasks/main.yml <==
- command: /bin/true
==> roles/db/handlers/main.yml <==
- name: db handler
command: echo db handler
==> roles/db/meta/main.yml <==
dependencies: [base]
==> roles/db/tasks/main.yml <==
- command: /bin/true
notify: [db handler, base handler]
Now I run ansible-playbook -i inventory playbook.yml which results in
PLAY [all] **********************************************************************
TASK [Gathering Facts] **********************************************************
ok: [server1]
ok: [server2]
TASK [base : command] ***********************************************************
skipping: [server2]
changed: [server1]
TASK [app : command] ************************************************************
skipping: [server2]
changed: [server1]
TASK [base : command] ***********************************************************
changed: [server2]
TASK [db : command] *************************************************************
skipping: [server1]
changed: [server2]
RUNNING HANDLER [base : base handler] *******************************************
skipping: [server2]
changed: [server1]
RUNNING HANDLER [app : app handler] *********************************************
changed: [server1]
RUNNING HANDLER [db : db handler] ***********************************************
changed: [server2]
PLAY RECAP **********************************************************************
server1 : ok=5 changed=4 unreachable=0 failed=0
server2 : ok=4 changed=3 unreachable=0 failed=0
Problem
My problem is that I expected both servers to execute the base handler. But apparently it is skipped on server2. If I add -v to the ansible command I get the unhelpful comment that skipping: [server2] => {"changed": false, "skip_reason": "Conditional result was False"}.
What also puzzles me is that the base role seems to be included twice and each server skips one or the other inclusion of the role respectively.
Question
Is there any way I can ensure that the handlers are fired correctly?
EDIT
Is it a bug that the handler is not fired or is that behavior documented somewhere?
/EDIT
minor questions
Is there any way to declare dependencies in a way that does not yield many inclusions which are only picked up by one server and ignored by all others although the others will include the same role through their own dependencies at some other point? This results in a lot of skipped tasks when I have some more servers and roles. (after reading the docs on role inclusion I suspect not)
Is there some other way to handle role dependencies and handlers with ansible? I came up with this setup after reading https://medium.com/#ibrahimgunduz34/parallel-playbook-execution-in-ansible-30799ccda4e0
Sidenote
I would like to avoid the group_by technique described in the docs, or more generally executing each role in their own playbook for the correct subset of the servers only, because I have a lot of servers and I want to speed up the run of the playbook by using strategy: free.
- hosts: Ebonding
become: yes
become_method: sudo
tasks
- name: Clearing cache of Server4
file: path=/weblogic/bea/user_projects/domains/tmp state=absent
become: yes
become_user: wls10
Ansible version 2.0.0.0 run the above playbook successfully::
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [ggnqinfa2]
TASK [Clearing cache of Server4] ***********************************************
ok: [ggnqinfa2]
PLAY RECAP *********************************************************************
ggnqinfa2 : ok=2 changed=0 unreachable=0 failed=0
But latest version of ansible 2.5.0rc2 encountered below error::
PLAY [Ebonding] *****************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************
ok: [ggnqinfa2]
TASK [Clearing cache of Server4] ************************************************************************************************************************************
fatal: [ggnqinfa2]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 2, err: chown: /var/tmp/ansible-tmp-1520704924.34-191458796685785/: Not owner\nchown: /var/tmp/ansible-tmp-1520704924.34-191458796685785/file.py: Not owner\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"}
PLAY RECAP **********************************************************************************************************************************************************
ggnqinfa2 : ok=1 changed=0 unreachable=0 failed=1
How can i run this playbook by latest version of ansible successfully?
Chances are the user you're using (wls10) does not have write access to the remote temporary directory /var/tmp.
This can be overridden using ansible.cfg and set via remote_tmp to a directory you have write-access to -- or, a "normal temp directory" (like /tmp) that has the sticky bit set.
For more info, see
http://docs.ansible.com/ansible/latest/intro_configuration.html#remote-tmp
Hope you can help work out why my playbook isn't completing as expected.
ENVIRONMENT
OSX El Capitan
ansible 2.1.0.0
CONFIGURATION
Nothing exciting:
[defaults]
roles_path=./roles
host_key_checking = False
ssh_args= -t -t
allow_world_readable_tmpfiles = True
PLAYBOOK
I have a reasonably involved setup with a number of plays in one playbook.
The playbook is run against different target systems; the production site and a dev rig. (Please don't suggest I combine them... it's an IoT system and complex enough as it is.)
Here's my somewhat redacted playbook:
- hosts: all
roles:
- ...
- hosts: xmpp_server
roles:
- ...
- hosts: audit_server
roles:
- ...
- hosts: elk_server
roles:
- ...
- hosts: all
roles:
- ...
Now, please bear in mind that I have an IoT setup with various redundancies, replication and distribution going on, so although there are other ways of skinning the cat, the above decomposition into multiple plays is really neat for my setup and I'd like to keep it.
Also important: I have no audit_server or elk_server hosts on my dev rig. Those groups are currently empty as I'm working on an orthogonal issue and don't need them consuming limited dev resources. I do have those in production, just not in dev.
EXPECTED BEHAVIOUR
On the production site I expect all the plays to trigger and run.
On the dev rig I expect the first play (all) and the xmpp_server play to run, the audit_server and elk_server plays to skip and the last (all) play to run after that.
ACTUAL BEHAVIOUR
The production site works exactly as expected. All plays run.
The dev rig completes the xmpp_server play as dev-piA is a member of the xmpp_server group. And then it silently stops. No error, no information, nothing. Just straight to the play recap. Here's the output:
...
TASK [xmppserver : include] ****************************************************
included: /Users/al/Studio/Projects/smc/ansible/roles/xmppserver/tasks/./openfire.yml for dev-piA
TASK [xmppserver : Get openfire deb file] **************************************
ok: [dev-piA]
TASK [xmppserver : Install openfire deb file] **********************************
ok: [dev-piA]
TASK [xmppserver : Check if schema has been uploaded previously] ***************
ok: [dev-piA]
TASK [xmppserver : Install openfire schema to postgres db] *********************
skipping: [dev-piA]
to retry, use: --limit #fel.retry
PLAY RECAP *********************************************************************
dev-vagrant1 : ok=0 changed=0 unreachable=1 failed=0
dev-piA : ok=106 changed=3 unreachable=0 failed=0
dev-piB : ok=77 changed=3 unreachable=0 failed=0
dev-piC : ok=77 changed=3 unreachable=0 failed=0
...
So, I ran it with -vvvvv and got nothing more useful:
...
TASK [xmppserver : Install openfire schema to postgres db] *********************
task path: /Users/al/Studio/Projects/smc/ansible/roles/xmppserver/tasks/openfire.yml:14
skipping: [dev-piA] => {"changed": false, "skip_reason": "Conditional check failed", "skipped": true}
to retry, use: --limit #fel.retry
PLAY RECAP *********************************************************************
dev-vagrant1 : ok=0 changed=0 unreachable=1 failed=0
dev-piA : ok=106 changed=2 unreachable=0 failed=0
dev-piB : ok=77 changed=3 unreachable=0 failed=0
dev-piC : ok=77 changed=3 unreachable=0 failed=0
...
HELP NEEDED
So, my question is: why does the playbook just stop there? What's going on?!
It doesn't actually explicitly say that there are no more hosts left for the audit_server play; that's my best guess. It just stops as if it hit an EOF.
I'm completely stumped.
Edit: NB: The retry file only contains a reference to the vagrant machine, which is currently off. But if the existence of that is the problem then Ansible's logic is very flawed. I'll check now just in case anyway
Edit: OMFG it actually IS the missing vagrant box, which has nothing to do with a goddamn thing. That's shocking and I'll raise it as an issue with Ansible. But... I'll leave this here in case anyone ever has the same problem and googles it.
Edit: For clarity, the vagrant machine is not in the host lists for any of the plays, except the special 'all' case.
Ansible aborts execution if every host in the play is unhealthy.
If dev-vagrant1 is the only member of audit_server group, this is the expected behavior (as we see dev-vagrant1 is marked as unreachable).
Nevertheless there should be a line PLAY [audit_server] ******** just before to retry, use...
Ansible folk got back to me and confirmed that they'd been working on a number of issues in this area for the 2.1.1 release.
I updated to 2.1.1.0 and it worked fine.