1

I want to pass variable called ssh_user from the first play on ansible playbook to next different host play. I have tried to use "set_fact" but seems like it's still can't retrieve variable from the previous play.

Below is my ansible playbook code:

- hosts: localhost

  vars_prompt:

    - name: target_host
      prompt: Target Host IP
      private: false
    - name: auth_method
      prompt: Authentication method (password/key)
      private: false

  vars:

    ssh_user: "{{ ssh_user_out.user_input }}"
    ssh_pass: "{{ ssh_pass_out.user_input }}"
    ssh_keypath: "{{ ssh_keypath_out.user_input }}"
    
  tasks:

    - block:
        - pause:
            prompt: SSH Username
          register: ssh_user_out
        - pause:
            prompt: SSH Password
            echo: false
          register: ssh_pass_out
        - set_fact:
            ssh_user: "{{ ssh_user }}"
            ssh_pass: "{{ ssh_pass }}"
      when: auth_method == 'password'

    - block:
        - pause:
            prompt: SSH Username
          register: ssh_user_out
        - pause:
            prompt: Private Key Path
          register: ssh_keypath_out
        - set_fact:
            ssh_user: "{{ ssh_user }}"
            ssh_keypath: "{{ ssh_keypath }}"
      when: auth_method == 'key'
    - add_host:
        name: "{{ target_host }}"
        groups: dynamically_created_hosts



- name: Download files from FTP on target host
  hosts: dynamically_created_hosts
  tasks:
    - name: set the facts per host
      set_fact:
        ssh_user: "{{hostvars['localhost']['ssh_user']}}"
        ssh_pass: "{{hostvars['localhost']['ssh_pass']}}"
        ssh_keypath: "{{hostvars['localhost']['ssh_keypath']}}"
  gather_facts: false
  remote_user: "{{ ssh_user }}"
  
  become: true
  become_user: root
  become_method: sudo

  tasks:
    - name: Create upgrade directory if not exist
      file:
        path: /root/upgrade
        state: directory

    - name: Download file from FTP
      get_url:
        url: "ftp://something.com/{{ file_path }}"
        dest: "/root/upgrade/{{ file_path }}"
        force: yes
        timeout: 30
        remote_src: yes
        validate_certs: false
        url_username: "{{ ftp_username }}"
        url_password: "{{ ftp_password }}"
      register: download_result
      ignore_errors: true

    - name: Check if file downloaded successfully
      debug:
        msg: "File '{{ file_path }}' downloaded successfully."
      when: download_result is success

    - name: Display error message if file download failed
      debug:
        msg: "Failed to download file '{{ file_path }}'. Please check the file path or FTP credentials."
      when: download_result is failed and file_path != 'q'

    - name: Exit playbook if 'q' is pressed
      meta: end_play
      when: file_path == 'q'

Below is the error:

WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
[WARNING]: While constructing a mapping from /Related/ansible/upgrade/upgrade.yml, line 50, column 3, found a duplicate
dict key (tasks). Using last defined value only.
Target Host IP: 192.168.10.1
Authentication method (password/key): password

PLAY [localhost] *******************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************
ok: [localhost]

TASK [pause] ***********************************************************************************************************************************************
[pause]
SSH Username:
ok: [localhost]

TASK [pause] ***********************************************************************************************************************************************
[pause]
SSH Password (output is hidden):
ok: [localhost]

TASK [set_fact] ********************************************************************************************************************************************
ok: [localhost]

TASK [pause] ***********************************************************************************************************************************************
skipping: [localhost]

TASK [pause] ***********************************************************************************************************************************************
skipping: [localhost]

TASK [set_fact] ********************************************************************************************************************************************
skipping: [localhost]

TASK [add_host] ********************************************************************************************************************************************
changed: [localhost]

PLAY [Download files from FTP on target host] **************************************************************************************************************

TASK [Create upgrade directory if not exist] ***************************************************************************************************************
fatal: [192.168.10.1]: FAILED! => {"msg": "The field 'remote_user' has an invalid value, which includes an undefined variable. The error was: 'ssh_user' is undefined. 'ssh_user' is undefined. 'ssh_user' is undefined. 'ssh_user' is undefined"}

PLAY RECAP *************************************************************************************************************************************************
192.168.10.1               : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
localhost                  : ok=5    changed=1    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   

as you can see even after I tried to call vars from previous play using set_fact and hostvars , it's still showing " {"msg": "The field 'remote_user' has an invalid value, which includes an undefined variable. The error was: 'ssh_user' is undefined. 'ssh_user' is undefined. 'ssh_user' is undefined. 'ssh_user' is undefined"}"

I have tried several ways on the similar case but none is working so far.

Appreciate your help!

1 Answers1

3

Declare the variables when adding the host. See the first example. For example,

    - add_host:
        name: "{{ target_host }}"
        groups: dynamically_created_hosts
        ssh_user: "{{ ssh_user|d('UNDEF') }}"
        ssh_pass: "{{ ssh_pass|d('UNDEF') }}"
        ssh_keypath: "{{ ssh_keypath|d('UNDEF') }}"

Set default values because some of the variables will be undefined.


  • Example of a complete playbook for testing
shell> cat pb.yml
- hosts: localhost

  vars_prompt:

    - name: target_host
      prompt: Target Host IP
      private: false
    - name: auth_method
      prompt: Authentication method (password/key)
      private: false

  vars:

    ssh_user: "{{ ssh_user_out.user_input }}"
    ssh_pass: "{{ ssh_pass_out.user_input }}"
    
  tasks:

    - block:
        - pause:
            prompt: SSH Username
          register: ssh_user_out
        - pause:
            prompt: SSH Password
            echo: false
          register: ssh_pass_out
      when: auth_method == 'password'

    - add_host:
        name: "{{ target_host }}"
        groups: dynamically_created_hosts
        ssh_user: "{{ ssh_user|d('UNDEF') }}"
        ssh_pass: "{{ ssh_pass|d('UNDEF') }}"
        ssh_keypath: "{{ ssh_keypath|d('UNDEF') }}"

- hosts: dynamically_created_hosts

  tasks:

    - debug:
        msg: |
          ssh_user: {{ ssh_user }}
          ssh_pass: {{ ssh_pass }}
          ssh_keypath: {{ ssh_keypath }}

gives

shell> ansible-playbook pb.yml
Target Host IP: 10.1.0.10
Authentication method (password/key): password

PLAY [localhost] ******************************************************************************

TASK [pause] **********************************************************************************
[pause]
SSH Username:
admin^Mok: [localhost]

TASK [pause] **********************************************************************************
[pause]
SSH Password (output is hidden):
ok: [localhost]

TASK [add_host] *******************************************************************************
changed: [localhost]

PLAY [dynamically_created_hosts] **************************************************************

TASK [debug] **********************************************************************************
ok: [10.1.0.10] => 
  msg: |-
    ssh_user: admin
    ssh_pass: 1234
    ssh_keypath: UNDEF

PLAY RECAP ************************************************************************************
10.1.0.10: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost: ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

  • Use set_fact to put variables into the hostvars. For example, the playbook below also does the job
shell> cat pb.yml
- hosts: localhost

  vars_prompt:

    - name: target_host
      prompt: Target Host IP
      private: false
    - name: auth_method
      prompt: Authentication method (password/key)
      private: false
    
  tasks:

    - block:
        - pause:
            prompt: SSH Username
          register: ssh_user_out
        - pause:
            prompt: SSH Password
            echo: false
          register: ssh_pass_out
        - set_fact:
            ssh_user: "{{ ssh_user_out.user_input }}"
            ssh_pass: "{{ ssh_pass_out.user_input }}"
      when: auth_method == 'password'

    - add_host:
        name: "{{ target_host }}"
        groups: dynamically_created_hosts

- hosts: dynamically_created_hosts

  vars:

    ssh_user: "{{ hostvars.localhost.ssh_user|d('UNDEF') }}"
    ssh_pass: "{{ hostvars.localhost.ssh_pass|d('UNDEF') }}"
    ssh_keypath: "{{ hostvars.localhost.ssh_keypath|d('UNDEF') }}"

  tasks:

    - debug:
        msg: |
          ssh_user: {{ ssh_user }}
          ssh_pass: {{ ssh_pass }}
          ssh_keypath: {{ ssh_keypath }}

gives

shell> ansible-playbook pb.yml
Target Host IP: 10.1.0.10
Authentication method (password/key): password

PLAY [localhost] ******************************************************************************

TASK [pause] **********************************************************************************
[pause]
SSH Username:
admin^Mok: [localhost]

TASK [pause] **********************************************************************************
[pause]
SSH Password (output is hidden):
ok: [localhost]

TASK [set_fact] *******************************************************************************
ok: [localhost]

TASK [add_host] *******************************************************************************
changed: [localhost]

PLAY [dynamically_created_hosts] **************************************************************

TASK [debug] **********************************************************************************
ok: [10.1.0.10] => 
  msg: |-
    ssh_user: admin
    ssh_pass: 1234
    ssh_keypath: UNDEF

PLAY RECAP ************************************************************************************
10.1.0.10: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost: ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
Vladimir Botka
  • 5,138
  • 8
  • 20