I have a playbook where I would like to do a task once before starting a couple roles and once after roles with serial 1. I thought I could accomplish this with pre and post tasks but it looks like they are called once per server.
you want run_once, not serial
My real use case is a patching playbook. I have a collection of servers I want to patch one at a time (serial: 1) but there are a set of decommision steps I only want to run once for the entire group. Then patch the servers one by one. Then there is a set of commission tasks I want to run once for the entire group. If I put run once on the pre/post tasks. It still gets run once per play eg once per host.
If it helps, the full context is this is a cassandra cluster. I want to stop the repair service, patch the whole cluster 1 node at a time, then start the repair service.
How to make this work is documented under note section of run_once.
http://docs.ansible.com/ansible/latest/playbooks_delegation.html#run-once
Thanks.
when: inventory_hostname == ansible_play_hosts[0]
Is exactly what I need.
In case someone else has this issue, for my post task I that I only want to run on the last host I used the below conditional. Results in skipped tasks but it does accomplish the goal. Not sure if there is a more elegant way to say run on the last host.
when: inventory_hostname == ansible_play_hosts[ ansible_play_hosts | length - 1]
This results in
TASK [command] **************************************************************************************************************************************
changed: [mdl-swch01] => {“changed”: true, “cmd”: “echo "pre"”, “delta”: “0:00:00.002647”, “end”: “2018-02-15 11:19:37.098522”, “rc”: 0, “start”: “2018-02-15 11:19:37.095875”, “stderr”: “”, “stderr_lines”: , “stdout”: “pre”, “stdout_lines”: [“pre”]}
TASK [command] **************************************************************************************************************************************
changed: [mdl-swch01] => {“changed”: true, “cmd”: “echo "task 1"”, “delta”: “0:00:00.003688”, “end”: “2018-02-15 11:19:43.144388”, “rc”: 0, “start”: “2018-02-15 11:19:43.140700”, “stderr”: “”, “stderr_lines”: , “stdout”: “task 1”, “stdout_lines”: [“task 1”]}
TASK [command] **************************************************************************************************************************************
changed: [mdl-swch01] => {“changed”: true, “cmd”: “echo "task 2"”, “delta”: “0:00:00.002865”, “end”: “2018-02-15 11:19:49.189866”, “rc”: 0, “start”: “2018-02-15 11:19:49.187001”, “stderr”: “”, “stderr_lines”: , “stdout”: “task 2”, “stdout_lines”: [“task 2”]}
TASK [command] **************************************************************************************************************************************
skipping: [mdl-swch01] => {“changed”: false, “skip_reason”: “Conditional result was False”}
PLAY [Hello World Linux] ****************************************************************************************************************************
TASK [command] **************************************************************************************************************************************
skipping: [mdl-swch02] => {“changed”: false, “skip_reason”: “Conditional result was False”}
TASK [command] **************************************************************************************************************************************
changed: [mdl-swch02] => {“changed”: true, “cmd”: “echo "task 1"”, “delta”: “0:00:00.002640”, “end”: “2018-02-15 11:19:50.853990”, “rc”: 0, “start”: “2018-02-15 11:19:50.851350”, “stderr”: “”, “stderr_lines”: , “stdout”: “task 1”, “stdout_lines”: [“task 1”]}
TASK [command] **************************************************************************************************************************************
changed: [mdl-swch02] => {“changed”: true, “cmd”: “echo "task 2"”, “delta”: “0:00:00.002785”, “end”: “2018-02-15 11:19:51.261013”, “rc”: 0, “start”: “2018-02-15 11:19:51.258228”, “stderr”: “”, “stderr_lines”: , “stdout”: “task 2”, “stdout_lines”: [“task 2”]}
TASK [command] **************************************************************************************************************************************
changed: [mdl-swch02] => {“changed”: true, “cmd”: “echo "post"”, “delta”: “0:00:00.003841”, “end”: “2018-02-15 11:19:51.683943”, “rc”: 0, “start”: “2018-02-15 11:19:51.680102”, “stderr”: “”, “stderr_lines”: , “stdout”: “post”, “stdout_lines”: [“post”]}
Gah not quite there. I use meta_end play when I calculate that a patch isn’t relevant so that we don’t spend time decomissioning a host that doesn’t need a patch. Problem is this skips the post_tasks if the last server in the group isn’t relevant. I tried using handlers but that results in 1 execution per node.
I think I might need to re-think my playbook organization and simplify. I could use a workflow in tower to accomplish this simpler without skipped tasks.
when: inventory_hostname == ansible_play_hosts | last
Maybe 3 plays in a playbook will work for you
- name: Pre
hosst:
- name: Main
hosts:
serial: 1
- name: Post
hosts:
Since you want to run 3 sets of tasks on different sets of servers it would be a lot cleaner to split your playbook into three plays instead of one:
-
hosts: patchgroup[0]
tasks: -
debug: msg=pre
-
hosts: patchgroup
serial: 1
tasks: -
debug: msg=patch
-
hosts: patchgroup[0]
tasks: -
debug: msg=post
This way you won’t have a bunch of skipped tasks and you can end_play during patching without affecting your post tasks, since they’re a separate play.
Thanks for the help everyone. That is exactly what I was missing. I forgot you could have different plays in the same playbook. My playbook now looks like: