Create an additional Ansible role to dynamically set Ansible SSH user depending on the defined conditionals.
How it works
The idea is very straightforward as it is based on the inventory hostname. Checks are performed locally, the defined Ansible SSH user fact is used later to perform the SSH connection.
- Determine remote address, use
ansible_host
variable if available,inventory_hostname
otherwise. - Set SSH username to
vagrant
if it does contain “vagrant
” string. - Set SSH username to
ansible
if it does not contain “vagrant
” string.
This step can be skipped as the default value can be set inside the Ansible configuration file. - Check SSH connection using defined SSH user and register output.
- Set SSH username to
root
when the connection was unsuccessful. - Check SSH connection to identify unreachable hosts and fail early.
This step can be skipped as it is here to simply fail early.
Fallback to the root
user means that the host is uninitialized.
The inventory
The inventory contains hosts. Ansible SSH user is not defined here.
--- lxd: hosts: vagrant01: ansible_host: 192.168.50.150 vagrant02: ansible_host: 192.168.50.151 kraken: cerberus:
The playbook
At first, execute the ansible_user
role, then continue as always.
--- - hosts: lxd gather_facts: no roles: - ansible_user - hosts: lxd tasks: - name: Determine target hostname set_fact: local_hostname: "{{ appliance.hostname | default(inventory_hostname) }}" - name: Set hostname hostname: name: "{{ local_hostname }}"
The role
Inspect the following code. Some parts are not necessary, like default user which can be defined inside the local Ansible configuration file,
--- - name: Determine remote address set_fact: ansible_user__connect_to: "{{ hostvars[inventory_hostname].ansible_host | default(inventory_hostname) }}" - name: Set SSH username to vagrant set_fact: ansible_ssh_user: vagrant when: "'vagrant' in inventory_hostname" changed_when: false delegate_to: localhost - name: Set SSH username to ansible set_fact: ansible_ssh_user: ansible when: "'vagrant' not in inventory_hostname" changed_when: false delegate_to: localhost - block: - name: Check SSH connection to verify {{ ansible_ssh_user }} user wait_for_connection: timeout: 5 register: ansible_user__check_command_output check_mode: no changed_when: false rescue: - name: Display unitialized or unreachable hosts debug: msg: "Hostname {{ inventory_hostname }} is not initialized" - name: Set SSH username to root set_fact: ansible_ssh_user: root changed_when: false when: ansible_user__check_command_output.failed == true - name: Check SSH connection to identify unreachable hosts and fail early wait_for_connection: timeout: 5 check_mode: no changed_when: false
You can modify and extend it to solve your problems, like automatically discovering and using the initial dietpi
or rpi
users.
Execute the playbook
Execute the playbook.
PLAY [lxd] *** TASK [ansible_user : Determine remote address] **** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] TASK [ansible_user : Set SSH username to vagrant] * ok: [vagrant01] ok: [vagrant02] TASK [ansible_user : Set SSH username to ansible] * ok: [kraken] ok: [cerberus] TASK [ansible_user : Check SSH connection to verify vagrant user] * ok: [vagrant01] ok: [kraken] ok: [vagrant02] ok: [cerberus] TASK [ansible_user : Set SSH username to root] **** TASK [ansible_user : Check SSH connection to identify unreachable hosts and fail early] * ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] PLAY [lxd] TASK [Gathering Facts] ok: [vagrant02] ok: [vagrant01] ok: [kraken] ok: [cerberus] TASK [Determine target hostname] **** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] TASK [Set hostname] *** --- before +++ after @@ -1 +1 @@ -hostname = ubuntu-focal +hostname = vagrant01 changed: [vagrant01] --- before +++ after @@ -1 +1 @@ -hostname = ubuntu-focal +hostname = vagrant02 changed: [vagrant02] ok: [kraken] ok: [cerberus] PLAY RECAP cerberus : ok=7 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 kraken : ok=7 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 vagrant01 : ok=7 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 vagrant02 : ok=7 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
Additional fallback behaviour.
PLAY [lxd] ***********************************************************************************************************************************************[29/1933] TASK [ansible_user : Determine remote address] ******************************************************************************************************************** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] TASK [ansible_user : Set SSH username to vagrant] ***************************************************************************************************************** ok: [vagrant01] ok: [vagrant02] TASK [ansible_user : Set SSH username to ansible] ***************************************************************************************************************** ok: [kraken] ok: [cerberus] TASK [ansible_user : Check SSH connection to verify vagrant user] ************************************************************************************************* [WARNING]: Unhandled error in Python interpreter discovery for host kraken: Failed to connect to the host via ssh: Warning: Permanently added '172.16.110.120' (ECDSA) to the list of known hosts. ansible1@172.16.110.120: Permission denied (publickey). [WARNING]: Unhandled error in Python interpreter discovery for host cerberus: Failed to connect to the host via ssh: Warning: Permanently added '172.16.110.210' (ECDSA) to the list of known hosts. ansible1@172.16.110.210: Permission denied (publickey). ok: [vagrant01] ok: [vagrant02] fatal: [kraken]: FAILED! => {"changed": false, "elapsed": 5, "msg": "timed out waiting for ping module test: Data could not be sent to remote host \"kraken\". Make sure this host can be reached over ssh: Warning: Permanently added '172.16.110.120' (ECDSA) to the list of known hosts.\r\nansible1@172.16.110.120: Permission denie d (publickey).\r\n"} fatal: [cerberus]: FAILED! => {"changed": false, "elapsed": 5, "msg": "timed out waiting for ping module test: Data could not be sent to remote host \"cerberus\". Make sure this host can be reached over ssh: Warning: Permanently added '172.16.110.210' (ECDSA) to the list of known hosts.\r\nansible1@172.16.110.210: Permission denied (publickey).\r\n"} TASK [ansible_user : Display unitialized or unreachable hosts] **************************************************************************************************** ok: [kraken] => { "msg": "Hostname kraken is not initialized" } ok: [cerberus] => { "msg": "Hostname cerberus is not initialized" } TASK [ansible_user : Set SSH username to root] ******************************************************************************************************************** ok: [kraken] ok: [cerberus] TASK [ansible_user : Check SSH connection to identify unreachable hosts and fail early] *************************************************************************** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] PLAY [lxd] ******************************************************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************************************************** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] TASK [Determine target hostname] ********************************************************************************************************************************** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] TASK [Set hostname] *********************************************************************************************************************************************** ok: [vagrant01] ok: [vagrant02] ok: [kraken] ok: [cerberus] PLAY RECAP ******************************************************************************************************************************************************** cerberus : ok=8 changed=0 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0 kraken : ok=8 changed=0 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0 vagrant01 : ok=7 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 vagrant02 : ok=7 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0