Reputation: 113
I'm currently writting an Ansible script which should update openssl on every host running Debian or CentOS. On the hosts our SSH-Keys are deposited for my own user or root. I want to check if my user is existing on the host, if not I want to authenticate with the root user. Is there a possibility to do this? I tried it with a bash command but I want to check if my user exists before I'm running the tasks. Maybe there are other solutions to my problem but I don't know them. Running this playbook throws a syntax error. My Script looks like this right now:
---
- hosts: "{{ host_group }}"
remote_user: "{{ username }}"
tasks:
# Check whether there's a existinig user or whether you have to use root
- name: Check whether there's your user on the machine
action: shell /usr/bin/getent passwd $username | /usr/bin/wc -l | tr -d ''
register: user_exist
remote_user: root
when: user_exist.stdout == 0
tags:
- users
# Install openssl on Ubuntu or Debian
- name: Install openssl on Ubuntu or Debian
become: True
become_user: root
apt: name=openssl state=latest
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
# Install openssl on CentOS or RHEL
- name: Install openssl on CentOS or RHEL
become: True
become_user: root
yum: name=openssl state=latest
when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
Upvotes: 11
Views: 35219
Reputation: 560
As another native solution that does not generate unreachable
s in the recap, you can use wait_for_connection
:
---
- name: Juggle SSH user
hosts: all
gather_facts: false # important!
tasks:
- name: Try connecting with default settings
ansible.builtin.wait_for_connection:
timeout: 3
ignore_errors: true
register: _ssh_user_test
- name: Set SSH user juggling fact
ansible.builtin.set_fact:
ansible_ssh_user: root
when: _ssh_user_test is failed
# ...
# Run your other tasks here
Upvotes: 0
Reputation: 81
A more native and elegant way to test your SSH connection is with the Ansible ping module (which verifies the end-to-end SSH connection, not ICMP), and to use the playbook keyword ignore_unreachable
, which was added in Ansible 2.7.
The technique below puts SSH testing into its own play where facts are not gathered; subsequent plays will gather facts as normal:
---
###
## First play: Dynamically configure SSH user
##
- hosts: "{{ host_group }}"
gather_facts: false # don't try to ssh yet!!
vars:
ansible_ssh_user: "{{ username }}"
tasks:
- name: "Test SSH connection"
ping: # <-- no args needed
ignore_unreachable: true
ignore_errors: true
changed_when: false
register: ssh_test
- name: "Fall back to root user?"
when: ssh_test.unreachable is defined
connection: local
set_fact:
ansible_ssh_user: root
###
## Next play: Install Stuff
###
- hosts: "{{ host_group }}"
tasks:
- name: Install openssl on Ubuntu or Debian
# ...
Upvotes: 8
Reputation: 68269
You can test the connection with local_action
first.
Ansible need to know how to connect to the host for sure, otherwise it will trigger host unreachable
error and skip remaining tasks for that host.
Something like this:
- hosts: myservers
gather_facts: no # or it will fail on the setup step
tasks:
- name: Test user
local_action: "command ssh -q -o BatchMode=yes -o ConnectTimeout=3 {{ inventory_hostname }} 'echo ok'"
register: test_user
ignore_errors: true
changed_when: false
- name: Do useful stuff
remote_user: "{{ test_user | success | ternary(omit, 'root') }}"
command: echo ok
Upvotes: 10