Yes, it's possible, but most solutions are going to look pretty complicated at first glance. You might be better off simply defining a "bootstrap" playbook that you only ever execute once. That's what I have to install python and setup initial user.
However, to answer the question directly, here's a solution that should work:
# Experiment to "fix" `ansible_user` depending upon host availability
- hosts: all
gather_facts: false # Otherwise initial connection will fail
vars:
- bootstrap_user: root
tasks:
- debug:
msg: |
ansible_user: {{ ansible_user | d('unset') }};
remote_user: {{ remote_user | d('unset') }}
- action: ping
ignore_unreachable: true # requires Ansible >= 2.7
ignore_errors: yes
register: pingtest
# Works (mostly) for Ansible >= 2.2.
# Might think this alone would work, but only if NOT *ALL* hosts failed up to
# this point, which makes running the playbook on only a single host pointless.
# Therefore, also set `ignore_unrechable` in `ping` above.
# - https://github.com/ansible/ansible/issues/26362
# - https://github.com/ansible/ansible/issues/19673
# - https://github.com/ansible/ansible/issues/18075
- meta: clear_host_errors
- name: set ansible_user if no ping failed
set_fact:
ansible_user: "{{ bootstrap_user }}"
when: pingtest.failed | d(pingtest.unreachable) | d(false)
- debug:
msg: "ansible_user: {{ ansible_user | d('unset') }}"
# Connect as ansible_user from here on
- name: Show remote user
shell: "echo $USER"
changed_when: false
In general, the following two refs will help you with understanding variables (and precedence, which is important here) as well as error recovery: