How to perform tasks only one host, based on previous output

199 views
Skip to first unread message

Kevin Csuka

unread,
Dec 8, 2016, 7:25:16 AM12/8/16
to Ansible Project
Hi,

My goal is to perform tasks only one host based on the output. Searched for --limit module to use in playbooks, but it is not present.

A shell script is executed on 3 nodes, which returns a boolean.

ok: [localMulti1] => {
    "variable": {
        ...
        "stdout": "true",
        ...
    }
}
ok: [localMulti2] => {
    "variable": {
        ...
        "stdout": "false",
        ...
    }
}
ok: [localMulti3] => {
    "variable": {
        ...
        "stdout": "false",
        ...
    }
}

How can I perform tasks on only on localMulti2? But not statically include the host (inventory_hostname == '...')

Failing with:

- shell: echo
  when: variable.stdout == "false" and ...

Kevin Csuka

unread,
Dec 9, 2016, 3:16:09 AM12/9/16
to Ansible Project
No guru's who can reply?

Brian Coca

unread,
Dec 14, 2016, 9:07:20 PM12/14/16
to ansible...@googlegroups.com
should be simple enough

- script: myscript
  register: myreturn

- command: othertask
  when: myreturn.stdout|bool 

​it will only execute 'othertask' on hosts in which the return is true.​


----------
Brian Coca

Kevin Csuka

unread,
Dec 15, 2016, 3:01:14 AM12/15/16
to Ansible Project
Sorry if my message was unclear. The goal is to perform 'othertask' on only ONE host, where the value is false.
Your script will execute 'othertask' on ALL the hosts where the value is false, in this case, TWO hosts.

Also, run_once will not work because it will only run on the first host, where the boolean is true.

Greg Langford

unread,
Dec 15, 2016, 6:18:23 AM12/15/16
to Ansible Project
Will the host be the same on each run?

If so you could put a guard round the task when ansible_inventory_hostname is equal to the desired host.

when: ansible_inventory_hostname == "desired-host-name"

Something like the above? Or maybe you could look into using delegated tasks http://docs.ansible.com/ansible/playbooks_delegation.html#delegation

Kind Regards

Kevin Csuka

unread,
Dec 15, 2016, 7:14:51 AM12/15/16
to Ansible Project
Host differ each run. The task will be included in a role.
Is it possible to do something like:
when: variable.stdout == "false"
Register: myVar

Task: a task
Shell: echo
When: myVar is defined
Delegate_to: "{{ first-host-where_myVar is defined }}"

Brian Coca

unread,
Dec 15, 2016, 9:58:47 AM12/15/16
to ansible...@googlegroups.com
Then just fail the 'true' host and now you can use run once with confidence only 'false' hosts got there.

- script: myscript
  register: myreturn
  failed_when: not myreturn.stdout|bool

- command: othertask
  run_once: true


----------
Brian Coca

Kevin Csuka

unread,
Dec 15, 2016, 10:32:22 AM12/15/16
to Ansible Project
That task would still run on only the first host, and not the second.
Run_once will only perform the task on the first host... 

Brian Coca

unread,
Dec 15, 2016, 10:54:10 AM12/15/16
to ansible...@googlegroups.com
Isn't that exactly what you wanted? if you want it to run on all 'false' hosts just remove the run_once


----------
Brian Coca

Kevin Csuka

unread,
Dec 15, 2016, 11:02:09 AM12/15/16
to Ansible Project

Let met clarify. This is my output.

ok: [localMulti1] => {
    "variable": {
        ...
        "stdout": "true",
        ...
    }
}
ok: [localMulti2] => {
    "variable": {
        ...
        "stdout": "false",
        ...
    }
}
ok: [localMulti3] => {
    "variable": {
        ...
        "stdout": "false",
        ...
    }
}

How can I configure ansible to perform only a task on the second node, where the stdout is false. Not the third node
Run_once will never work, because it will always run it on the second host.


Brian Coca

unread,
Dec 15, 2016, 11:12:03 AM12/15/16
to ansible...@googlegroups.com
>How can I configure ansible to perform only a task on the second node, where the stdout is false. Not the third node
> Run_once will never work, because it will always run it on the second host. 

you realize you are giving contradictory statements?

you want it to run on the 2nd, not the 3rd but run once will never work because it will run on the 2nd????


----------
Brian Coca

Kevin Csuka

unread,
Dec 16, 2016, 3:13:57 AM12/16/16
to Ansible Project
Hihi, you're right. My bad, meant run_once will always run on the 1st node. 
Anyway...

Brian Coca

unread,
Dec 16, 2016, 12:18:00 PM12/16/16
to ansible...@googlegroups.com
not in my example, as the first node is removed from the play.


----------
Brian Coca

Kevin Csuka

unread,
Dec 16, 2016, 1:01:48 PM12/16/16
to Ansible Project
Nodes are excluded from a play when they fail. This is not the desired output.
I don't want to fail a task, I want it set-up as it should.

Kevin Csuka

unread,
Dec 16, 2016, 1:12:19 PM12/16/16
to Ansible Project
Here is a playbook to test it locally.
---
- hosts: my-3-nodes
  tasks:
    - stat:
        path: /tmp/hi
      register: me
      
    - shell: echo
      when: me.stat.exists == true and ...


On node 2 and 3 perform:
$: touch /tmp/hi

Brian Coca

unread,
Dec 16, 2016, 1:52:05 PM12/16/16
to ansible...@googlegroups.com
You keep changing the goalpost, now you want it to execute on every node? then  when: me.stat.exists == False is all you need.


----------
Brian Coca

Kevin Csuka

unread,
Dec 16, 2016, 2:20:49 PM12/16/16
to Ansible Project
That would still perform it only on host 2 and 3.
Goal: perform task only one node 2 or 3 where the output is, in this case, true.

Thank you so much for your support :)

Brian Coca

unread,
Dec 16, 2016, 2:31:40 PM12/16/16
to ansible...@googlegroups.com
Then my first suggestion works for that case.


----------
Brian Coca

Kevin Csuka

unread,
Dec 16, 2016, 2:48:54 PM12/16/16
to Ansible Project
Not what I desire, because it will perform the task on both 2 and 3.
I only desire to perform a task on 2 OR 3.

Brian Coca

unread,
Dec 16, 2016, 2:56:52 PM12/16/16
to ansible...@googlegroups.com
run_once prevents that


----------
Brian Coca

Kevin Csuka

unread,
Dec 16, 2016, 2:59:19 PM12/16/16
to Ansible Project
No it does not. run_once will only perform a task on node1, therefor skip the task.
Please re-check in a local environment.

Brian Coca

unread,
Dec 16, 2016, 3:37:45 PM12/16/16
to ansible...@googlegroups.com
last time i explain this:

- script: myscript
  register: myreturn
  failed_when: not myreturn.stdout|bool

# ^ this will remove host 1 from the host list so the next task only chooses 'first host' from 2 and 3

- command: othertask
  run_once: true

# ^ this task runs against ONLY 2 OR 3


----------
Brian Coca

Kai Stian Olstad

unread,
Dec 16, 2016, 5:29:39 PM12/16/16
to ansible...@googlegroups.com
- set_fact:
run_on: "{{ item }}"
with_items: "{{ play_hosts }}"
when: run_on is undefined and hostvars[item].me.stat.exists
run_once: true

- shell: echo
when: inventory_hostname == run_on


--
Kai Stian Olstad

Kevin Csuka

unread,
Dec 17, 2016, 8:08:25 AM12/17/16
to Ansible Project
This will FAIL the task at node 1, which is in no way desired. That is no real solution.
Also, after 'othertask' has been run, I'd like to perform other tasks on node 1.

Kevin Csuka

unread,
Dec 17, 2016, 8:09:21 AM12/17/16
to Ansible Project, ansible-pr...@olstad.com
Hallelujah! You did it. Big thanks to you sir!

TASK [command] *****************************************************************

Saturday 17 December 2016  14:08:12 +0100 (0:00:00.101)       0:00:01.122 *****

skipping: [localMulti1]

skipping: [localMulti3]

changed: [localMulti2]


PLAY RECAP *********************************************************************

localMulti1                : ok=3    changed=0    unreachable=0    failed=0

localMulti2                : ok=3    changed=1    unreachable=0    failed=0

localMulti3                : ok=2    changed=0    unreachable=0    failed=0

Arbab Nazar

unread,
Dec 17, 2016, 2:08:58 PM12/17/16
to Ansible Project, ansible-pr...@olstad.com
Kevin, can you please show the playbook/tasks that are working for you so that it will help others. Thanks

Kevin Csuka

unread,
Dec 17, 2016, 4:23:32 PM12/17/16
to Ansible Project
Erhm, the solution is in the quoted text..
Here is a copy/paste:
Reply all
Reply to author
Forward
0 new messages