Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2021-05-25T09:40:13.633Z
Answers: 2021-05-25T09:40:13.633Z
Answers: Jim ReesPotter
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2023-08-14T18:23:58.917Z
Answers: 2023-08-14T18:23:58.917Z
Answers: Lars Nieuwenhuizen
Body: <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>
  
Comments: CC BY-SA 4.0
Comments: 2021-05-25T05:29:14.203Z
Comments: 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
Comments: Bruce Becker
Tags: <kubernetes><ansible>
Title: How to use facts from one host to perform actions on another host?
UserDisplayName: Jim ReesPotter
ThreadText: # 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
  
  
  ---
  
  