How to prompt user for a target host in Ansible?

2019-01-09 08:05发布

问题:

I want to write a bootstrapper playbook for new machines in Ansible which will reconfigure the network settings. At the time of the first execution target machines will have DHCP-assigned address.

The user who is supposed to execute the playbook knows the assigned IP address of a new machine. I would like to prompt the user for is value.

vars_prompt module allows getting input from the user, however it is defined under hosts section effectively preventing host address as the required value.

Is it possible without using a wrapper script modifying inventory file?

回答1:

The right way to do this is to create a dynamic host with add_host and place it in a new group, then start a new play that targets that group. That way, if you have other connection vars that need to be set ahead of time (credentials/keys/etc) you could set them on an empty group in inventory, then add the host to it dynamically. For example:

- hosts: localhost
  gather_facts: no
  vars_prompt:
  - name: target_host
    prompt: please enter the target host IP
    private: no
  tasks:
    - add_host:
        name: "{{ target_host }}"
        groups: dynamically_created_hosts

- hosts: dynamically_created_hosts
  tasks:
  - debug: msg="do things on target host here"


回答2:

You could pass it with extra-vars instead.

Simply make your hosts section a variable such as {{ hosts_prompt }} and then pass the host on the command line like so:

ansible-playbook -i inventory/environment playbook.yml --extra-vars "hosts_prompt=192.168.1.10"

Or if you are using the default inventory file location of /etc/ansible/hosts you could simply use:

ansible-playbook playbook.yml --extra-vars "hosts_prompt=192.168.1.10"


回答3:

Adding to Matt's answer for multiple hosts.

input example would be 192.0.2.10,192.0.2.11

- hosts: localhost
  gather_facts: no
  vars_prompt:
  - name: target_host
    prompt: please enter the target host IP
    private: no
  tasks:
    - add_host:
        name: "{{ item }}"
        groups: dynamically_created_hosts
      with_items: "{{ target_host.split(',') }}"


- hosts: dynamically_created_hosts
  tasks:
  - debug: msg="do things on target host here"


回答4:

Disclaimer: The accepted answer offers the best solution to the problem. While this one is working it is based on a hack and I leave it as a reference.

I found out it was possible use a currently undocumented hack (credit to Bruce P for pointing me to the post) that turns the value of -i / --inventory parameter into an ad hoc list of hosts (reference). With just the hostname/ip address and a trailing space (like below) it refers to a single host without the need for the inventory file to exist.

Command:

ansible-playbook -i "192.168.1.21," playbook.yml

And accordingly playbook.yml can be run against all hosts (which in the above example will be equal to a single host 192.168.1.21):

- hosts: all 

The list might contain more than one ip address -i "192.168.1.21,192.168.1.22"