<p>I found a solution - the trick here is <em>delegate_to</em> and <em>delegate_facts</em>:</p>
<pre><code>- hosts: all
  remote_user: ansible
  become: false

  tasks:
  - name: read join line from controlPlane
    shell: kubeadm token create --print-join-command
    when: inventory_hostname in groups['workerNodes']
    register: joinCmd
    delegate_to: &quot;{{ item }}&quot;
    delegate_facts: true
    with_items: &quot;{{ groups['controlPlane'] }}&quot;

  - name: join all worker nodes to cluster
    command: &quot;{{ joinCmd.results[0].stdout }}&quot;
    become: yes
    when: inventory_hostname in groups['workerNodes']
</code></pre>
<p>The first task kind of reads backwards to my mind - <em>when</em> says 'run this task on all the  workerNode hosts...' but <em>delegate_to</em> says '..but actually run it on a different host'. It works for me though (I've only got 1 host in controlPlane group, not sure of outcome with more hosts).</p>

CC BY-SA 4.0
2021-05-25T09:40:13.633Z
2021-05-25T09:40:13.633Z
Jim ReesPotter
<p>Another option here would be to run tasks on the master node(s) to create the join command and just run the role for nodes joining based on the same conditions:</p>
<pre><code>- hosts: cluster_masters,cluster_workers
  pre_tasks:
    - name: Create the token to join
      ansible.builtin.shell: |
        kubeadm token create --print-join-command
      register: join_command
      when: inventory_hostname in groups.cluster_masters
    - name: Set token as fact
      ansible.builtin.set_fact:
        join_command: &quot;{{ join_command.stdout }}&quot;
      run_once: true
      when: inventory_hostname in groups.cluster_masters
  roles:
    - role: applications/kubernetes/node
      when: inventory_hostname in groups.cluster_workers and join_command is defined
</code></pre>
<p>The join_command is now availabe in the role</p>

CC BY-SA 4.0
2023-08-14T18:23:58.917Z
2023-08-14T18:23:58.917Z
Lars Nieuwenhuizen
<p>In Ansible I'm trying to generate a variable from a task on one host and then use the variable to do something to another host. Specifically, I'm trying to create a Kubernetes cluster - On the control plane node I can save the join command into a variable, but this appears to be scoped to the source host only - I can't work out how to access that variable from another host.</p>
<pre><code>- name: read join command from the controlPlane
  shell: kubeadm token create --print-join-command
  when: inventory_hostname in groups['controlPlane']
  register: joinCmd

- name: join worker nodes to cluster
  command: &quot;{{ joinCmd.stdout }}&quot;
  when: inventory_hostname in groups['workerNodes']
</code></pre>
<p>The above fails on the second task (<em>The task includes an option with an undefined variable. the error was: 'dict object' has no attribute 'stdout'</em>). The standard approach seems to be save the line to a file locally, copy the file to the worker nodes and execute it locally which seems cumbersome (and leaves the join token lying around).</p>
<p>How can I achieve this with variables only?</p>

CC BY-SA 4.0
2021-05-25T05:29:14.203Z
i may be mistaken, but you may need a separate play. I seem to remember that host vars are re-evaluated when a new play is started
Bruce Becker
<kubernetes><ansible>
How to use facts from one host to perform actions on another host?
Jim ReesPotter
# How to use facts from one host to perform actions on another host?

(Asked by: username_0 on 2021-05-24)

In Ansible I'm trying to generate a variable from a task on one host and then use the variable to do something to another host. Specifically, I'm trying to create a Kubernetes cluster - On the control plane node I can save the join command into a variable, but this appears to be scoped to the source host only - I can't work out how to access that variable from another host.
- name: read join command from the controlPlane
  shell: kubeadm token create --print-join-command
  when: inventory_hostname in groups['controlPlane']
  register: joinCmd

- name: join worker nodes to cluster
  command: "{{ joinCmd.stdout }}"
  when: inventory_hostname in groups['workerNodes']

The above fails on the second task (The task includes an option with an undefined variable. the error was: 'dict object' has no attribute 'stdout'). The standard approach seems to be save the line to a file locally, copy the file to the worker nodes and execute it locally which seems cumbersome (and leaves the join token lying around).
How can I achieve this with variables only?

**Tags:** kubernetes, ansible

> **Comments:**
> **username_1**: i may be mistaken, but you may need a separate play. I seem to remember that host vars are re-evaluated when a new play is started  

---

## 2 answers

### Answer by username_0 on 2021-05-25. Score: 2

I found a solution - the trick here is delegate_to and delegate_facts:
- hosts: all
  remote_user: ansible
  become: false

  tasks:
  - name: read join line from controlPlane
    shell: kubeadm token create --print-join-command
    when: inventory_hostname in groups['workerNodes']
    register: joinCmd
    delegate_to: "{{ item }}"
    delegate_facts: true
    with_items: "{{ groups['controlPlane'] }}"

  - name: join all worker nodes to cluster
    command: "{{ joinCmd.results[0].stdout }}"
    become: yes
    when: inventory_hostname in groups['workerNodes']

The first task kind of reads backwards to my mind - when says 'run this task on all the  workerNode hosts...' but delegate_to says '..but actually run it on a different host'. It works for me though (I've only got 1 host in controlPlane group, not sure of outcome with more hosts).


---

### Answer by username_2 on 2023-08-14. Score: 1

Another option here would be to run tasks on the master node(s) to create the join command and just run the role for nodes joining based on the same conditions:
- hosts: cluster_masters,cluster_workers
  pre_tasks:
    - name: Create the token to join
      ansible.builtin.shell: |
        kubeadm token create --print-join-command
      register: join_command
      when: inventory_hostname in groups.cluster_masters
    - name: Set token as fact
      ansible.builtin.set_fact:
        join_command: "{{ join_command.stdout }}"
      run_once: true
      when: inventory_hostname in groups.cluster_masters
  roles:
    - role: applications/kubernetes/node
      when: inventory_hostname in groups.cluster_workers and join_command is defined

The join_command is now availabe in the role


---

