Ansible file copy with sudo fails after upgrading to 1.9 - linux

In a playbook, I copy files using sudo. It used to work... Until we migrated to Ansible 1.9... Since then, it fails with the following error message:
"ssh connection closed waiting for sudo password prompt"
I provide the ssh and sudo passwords (through the Ansible prompt), and all the other commands running through sudo are successful (only the file copy and template fail).
My command is:
ansible-playbook -k --ask-become-pass --limit=testhost -C -D playbooks/debug.yml
and the playbookd contains:
- hosts: designsync
gather_facts: yes
tasks:
- name: Make sure the syncmgr home folder exists
action: file path=/home/syncmgr owner=syncmgr group=syncmgr mode=0755 state=directory
sudo: yes
sudo_user: syncmgr
- name: Copy .cshrc file
action: copy src=roles/designsync/files/syncmgr.cshrc dest=/home/syncmgr/.cshrc owner=syncmgr group=syncmgr mode=0755
sudo: yes
sudo_user: syncmgr
Is this a bug or did I miss something?
François.

Your playbook should look like:
- hosts: designsync
gather_facts: yes
tasks:
- name: Make sure the syncmgr home folder exists
sudo: yes
sudo_user: syncmgr
file:
path: "/home/syncmgr"
owner: syncmgr
group: syncmgr
mode: 0755
state: directory
- name: Copy .cshrc file
sudo: yes
sudo_user: syncmgr
copy:
src: "roles/designsync/files/syncmgr.cshrc"
dest: "/home/syncmgr/.cshrc"
owner: syncmgr
group: syncmgr
mode: 0755

Depending on the exact version of Ansible you're using, there may be a bug with sudo_user (experienced it myself).
Trying changing your playbooks from "sudo_user" to "remote_user".

Related

pm2 unable to register service on port when started with ansible

I have the following ansible playbook
- name: "update apt package."
become: yes
apt:
update_cache: yes
- name: "update packages"
become: yes
apt:
upgrade: yes
- name: "Remove dependencies that are no longer required"
become: yes
apt:
autoremove: yes
- name: "Install Dependencies"
become: yes
apt:
name: ["nodejs", "npm"]
state: latest
update_cache: yes
- name: Install pm2
become: yes
npm:
name: pm2
global: yes
production: yes
state: present
- name: Creates Directory
become: yes
file:
path: ~/backend
state: directory
mode: 0755
- name: Copy backend dist files web server
become: yes
copy:
src: ~/project/artifact.tar.gz
dest: ~/backend/artifact.tar.gz
- name: Extract backend files
become: yes
shell: |
cd ~/backend
tar -vxf artifact.tar.gz
#pwd
- name: Executing node
become: true
become_method: sudo
become_user: root
shell: |
cd ~/backend
npm install
npm run build
pm2 stop default
pm2 start npm --name "backend" -- run start --port 3030
pm2 status
cd ~/backend/dist
pm2 start main.js --update-env
pm2 status
I have the following issue with the task Executing node. So on my remote server, if I run each of the commands manually, after logging onto the remote machine via SSH, as root user, pm2 starts the services as expected as I can also confirm from pm2 status. I can also verify that the service is bound to port 3030 and listening on it (as expected).
But when I try doing the same using Ansible playbook, PM2 does start the service, but for some reason it does not bind the service to the port 3030 as I can see there is nothing listening on 3030.
Can someone please help?
Major edit 1
I also tried breaking up the entire task into smaller ones and run them as individual commands through the command module. But the results are still the same.
Updated roles playbook:
- name: "update apt package."
become: yes
apt:
update_cache: yes
- name: "update packages"
become: yes
apt:
upgrade: yes
- name: "Remove dependencies that are no longer required"
become: yes
apt:
autoremove: yes
- name: "Install Dependencies"
become: yes
apt:
name: ["nodejs", "npm"]
state: latest
update_cache: yes
- name: Install pm2
become: yes
npm:
name: pm2
global: yes
production: yes
state: present
- name: Creates Directory
become: yes
file:
path: ~/backend
state: directory
mode: 0755
- name: Copy backend dist files web server
become: yes
copy:
src: ~/project/artifact.tar.gz
dest: ~/backend/artifact.tar.gz
#dest: /home/ubuntu/backend/artifact.tar.gz
- name: Extract backend files
become: yes
shell: |
cd ~/backend
tar -vxf artifact.tar.gz
- name: NPM install
become: true
command: npm install
args:
chdir: /root/backend
register: shell_output
- name: NPM build
become: true
command: npm run build
args:
chdir: /root/backend
register: shell_output
- name: PM2 start backend
become: true
command: pm2 start npm --name "backend" -- run start
args:
chdir: /root/backend
register: shell_output
- name: PM2 check backend status in pm2
become: true
command: pm2 status
args:
chdir: /root/backend
register: shell_output
- name: PM2 start main
become: true
command: pm2 start main.js --update-env
args:
chdir: /root/backend/dist
register: shell_output
- debug: var=shell_output
No change in the result even with the above:
while running the same manually, either individually each command on the bash shell or through a .sh script (as below) works just fine.
#!/bin/bash
cd ~/backend
pm2 start npm --name "backend" -- run start
pm2 status
cd dist
pm2 start main.js --update-env
pm2 status
pm2 save
Sometimes, even the manual steps also do not get the port up and listening while the service is still up. But this happens rarely and I am unable to consistently reproduce this issue.
Why is this not working is my primary question. What's am I doing wrong? My assumption is that, conceptually, it should work.
My secondary question is how can I make this work?

Ansible Make build "cmd"the input device is not a TTY error

i am trying to automate a process with Ansible. I need to automate a build using make process. i have used this script
- hosts: localhost
tasks:
- name: Remove file (delete file)
file:
path: /opt/ansible-deploy
state: absent
- name: Read-write git checkout from github
git:
repo: git repo
dest: /opt/dir
version: repo
- name: Clean Directory
shell: |
mkdir -p /opt/dir/build
cd /opt/dir/build
cmake ..
- name: Build the default target
community.general.make:
chdir: /opt/dir/build/
I am getting error for "the input device is not a TTY\nmake[2]
fatal: [localhost]: FAILED! => {"changed": false, "cmd": "/usr/bin/make", "msg": "the input device is not a TTY\nmake[2]: ***
Can any experts help me with this error?

Error running playbook that only affects one of the hosts

I've recently started using more and more Ansible, and especially AWX, for simple repetitive tasks. Below is a playbook for downloading, installing and configuring logging via a Bash script. The script is for two hosts: Ubuntu 20.04 and CentOS 7.6, and for the latter, making some changes to SELinux is required.
The question is, why am I getting an error for the Ubuntu only and not the CentOS also?
Here is the playbook:
# Download an run Nagios Log Server configuration script
---
- name: nagios-log configure
hosts: all
remote_user: root
tasks:
- name: Distribution
debug: msg="{{ ansible_distribution }}"
- name: Download setup-linux.sh
get_url:
url: http://10.10.10.10/nagioslogserver/scripts/setup-linux.sh
validate_certs: no
dest: /tmp/setup-linux.sh
- name: Change script permission
file: dest=/tmp/setup-linux.sh mode=a+x
- name: Run setup-linux.sh
shell: /tmp/setup-linux.sh -s 10.10.10.10 -p 5544
register: ps
failed_when: "ps.rc not in [ 0, 1 ]"
- name: Install policycoreutils if needed
yum:
name:
- policycoreutils
- policycoreutils-python
state: latest
when: ansible_distribution == 'CentOS'
- name: Check if policy file exists
stat:
path: /etc/selinux/targeted/active/ports.local
register: result
when: ansible_distribution == 'CentOS'
- name: Check whether line exists
find:
paths: /etc/selinux/targeted/active/ports.local
contains: '5544'
register: found
when: result.stat.exists == True
- name: Add SELinux policy exception if missing
command: semanage port -a -t syslogd_port_t -p udp 5544
when: found.matched > 0
- name: Restart rsyslog
systemd:
name: rsyslog
state: restarted
enabled: yes
And here is the error output when running the playbook on AWX:
TASK [Check whether line exists] ***********************************************
fatal: [Ubuntu.domain.corp]: FAILED! => {"msg": "The conditional check 'result.stat.exists == True' failed. The error was: error while evaluating conditional (result.stat.exists == True): 'dict object' has no attribute 'stat'\n\nThe error appears to be in '/tmp/awx_154_1811rny6/project/nagios-log.yml': line 39, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Check whether line exists\n ^ here\n"}
ok: [Centos.domain.corp]
For reasons I can't comprehend, the CentOS server is fine, but the Ubuntu is getting a strange error that I don't understand. I've tried other methods to achieve the same logic as the when command.
You get this error, because you register the variable result in
- name: Check if policy file exists
stat:
path: /etc/selinux/targeted/active/ports.local
register: result
when: ansible_distribution == 'CentOS'
But because of when: ansible_distribution == 'CentOS' this does not run on Ubuntu and therefor the variable result does not exist when running the playbook on Ubuntu.
To fix this (and run the task using result on CentOS only as well) you can change it to this:
- name: Check whether line exists
find:
paths: /etc/selinux/targeted/active/ports.local
contains: '5544'
register: found
when:
- ansible_distribution == 'CentOS'
- result.stat.exists == True
- name: Add SELinux policy exception if missing
command: semanage port -a -t syslogd_port_t -p udp 5544
when:
- ansible_distribution == 'CentOS'
- found.matched > 0
Or you can put all CentOS specific tasks in a block like this:
- name: CentOS specific tasks
block:
- name: Install policycoreutils if needed
yum:
name:
- policycoreutils
- policycoreutils-python
state: latest
- name: Check if policy file exists
stat:
path: /etc/selinux/targeted/active/ports.local
register: result
- name: Check whether line exists
find:
paths: /etc/selinux/targeted/active/ports.local
contains: '5544'
register: found
when: result.stat.exists == True
- name: Add SELinux policy exception if missing
command: semanage port -a -t syslogd_port_t -p udp 5544
when: found.matched > 0
when: ansible_distribution == 'CentOS'
Or you can put them in their own file and include that file. There are actually a lot of ways to do this.

Why profile does not get loaded properly?

I have run a playbook with the following content on host:
---
- name: Test
hosts: debian
vars_files:
- "./secret.vault.yaml"
tasks: # Roles, modules, and any variables
- name: Install aptitude using apt
apt: name=aptitude state=latest update_cache=yes force_apt_get=yes
- name: Install required system packages
apt: name={{ item }} state=latest update_cache=yes
loop:
[
"apt-transport-https",
"ca-certificates",
"curl",
"software-properties-common",
"python3-pip",
"virtualenv",
"python3-setuptools",
]
- name: Install snap
apt:
update_cache: yes
name: snapd
- name: Install git
apt:
update_cache: yes
name: git
- name: Install certbot
apt:
update_cache: yes
name: certbot
- name: Install htop
apt:
update_cache: yes
name: htop
- name: Ensure group "sudo" exists
group:
name: sudo
state: present
- name: Add Docker GPG apt Key
apt_key:
url: https://download.docker.com/linux/debian/gpg
state: present
- name: Add Docker Repository
apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/debian buster stable
state: present
- name: Index new repo into the cache
apt:
name: "*"
state: latest
update_cache: yes
force_apt_get: yes
- name: Update apt and install docker-ce
apt:
update_cache: yes
name: docker-ce
state: latest
- name: Ensure group "docker" exists
group:
name: docker
state: present
- name: Add admin user
user:
name: admin
comment: administrator
groups: sudo, docker
password: "{{ adminpw | password_hash('sha512') }}"
- name: Ensure docker-compose is installed and available
get_url:
url: https://github.com/docker/compose/releases/download/1.25.4/docker-compose-{{ ansible_system }}-{{ ansible_userspace_architecture }}
dest: /usr/local/bin/docker-compose
mode: "u=rwx,g=rx,o=rx"
- name: Copy SSH file
copy:
src: ~/.ssh
dest: /home/admin/
force: yes
owner: admin
group: admin
remote_src: yes
When I try to login ssh admin#xxx.xxx.xxx.xxx, the .profile does not get loaded correctly:
after typing the bash command, it shows:
properly.
I triggered the playbook as follows:
ansible-playbook playbook.yaml -i ./hosts -u root --ask-vault-pass
What am doing wrong?
It appears based on your "after typing bash" statement that you are expecting the user's shell to be /bin/bash but is not; if that's your question, then you need to update the user: task to specify the shell you want:
- name: Add admin user
user:
name: admin
shell: /bin/bash

Ansible copy module does not support backup of directory and permissions of directory

In the official documentation also its mentioned that copy works on files.
I am able to copy a directory but can not take the backup of existing directory.
What could be the best way to do it without shell/command module ? Something directly ansible or am i missing something with copy module ?
Also same permissions 0777 set for file work but not for directory.
Use the synchronize module for your backups and restores.
- name: back up remote dir to local
hosts: localhost
tasks:
- synchronize:
src: /dir/for/backup
dest: "{{ ansible_default_ipv4.address }}":/dir/to/store/backup
recursive: yes
perms: yes
delegate_to: <remote_host>
- name: restore local dir to remote
hosts: <remote_hosts>
tasks:
- synchronize:
src: /path/to/backup/dir
dest: /path/to/dest/dir
recursive: yes
perms: yes
delete: yes

Resources