ansible copy module AnsibleUndefined error - ansible

I have below task to copy the content of file difference and there is no error but it output "AnsibleUndefined " into destination file
- name: dff tesk
local_action: shell diff -s --unified=0 /src/path/{{ item }} /dest/path/{{ item }}
with_items:
- file1.yml
- file2.yml
register: file_cmp
- name: copy
copy:
content: "{{ file_cmp.results | map(attribute='stdout') | list }}"
dest: "/path/to_dest/file_cmp.log
remote_src: yes
The task do not result in any error and create output file with content
AnsibleUndefined,AnsibleUndefined,AnsibleUndefined,AnsibleUndefined,AnsibleUndefined
The same playbook works and generate correct when executed locally.
"results": [
{
"ansible_loop_var" : "item"
"changed": "false"
"failed": "false"
"failed_when_result":"false"
"item": "fail1.yml"
"module_stderr":"sudo : effective uid is not 0 is /bin/sudo on a file system with the nosuid option set or an NFS file system without root priviledges ?" "msg": "MODULE FAILURE"
"rc": "1"

Related

Getting Ansible runtime error dict object' has no attribute 'stdout_lines' despite variable not null

Below is my playbook which has a variable running_processes which contains a list of pids(one or more)
Next, I read the user ids for each of the pids. All good so far.
I then try to print the list of user ids in curr_user_ids variable using -debug module is when i get the error: 'dict object' has no attribute 'stdout_lines'
I was expecting the curr_user_ids to contain one or more entries as evident from the output shared below.
- name: Get running processes list from remote host
shell: "ps -few | grep java | grep -v grep | awk '{print $2}'"
changed_when: false
register: running_processes
- name: Gather USER IDs from processes id before killing.
shell: "id -nu `cat /proc/{{ running_processes.stdout }}/loginuid`"
register: curr_user_ids
with_items: "{{ running_processes.stdout_lines }}"
- debug: msg="USER ID LIST HERE:{{ curr_user_ids.stdout }}"
with_items: "{{ curr_user_ids.stdout_lines }}"
TASK [Get running processes list from remote host] **********************************************************************************************************
task path: /app/wls/startstop.yml:22
ok: [10.9.9.111] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "cmd": "ps -few | grep java | grep -v grep | awk '{print $2}'", "delta": "0:00:00.166049", "end": "2019-11-06 11:49:42.298603", "rc": 0, "start": "2019-11-06 11:49:42.132554", "stderr": "", "stderr_lines": [], "stdout": "24032", "stdout_lines": ["24032"]}
TASK [Gather USER IDS of processes id before killing.] ******************************************************************************************************
task path: /app/wls/startstop.yml:59
changed: [10.9.9.111] => (item=24032) => {"ansible_loop_var": "item", "changed": true, "cmd": "id -nu `cat /proc/24032/loginuid`", "delta": "0:00:00.116639", "end": "2019-11-06 11:46:41.205843", "item": "24032", "rc": 0, "start": "2019-11-06 11:46:41.089204", "stderr": "", "stderr_lines": [], "stdout": "user1", "stdout_lines": ["user1"]}
TASK [debug] ************************************************************************************************************************************************
task path: /app/wls/startstop.yml:68
fatal: [10.9.9.111]: FAILED! => {"msg": "'dict object' has no attribute 'stdout_lines'"}
Can you please suggest why am I getting the error and how can I resolve it ?
Few points to note why your solution didn't work.
The task Get running processes list from remote host returns a newline splitted \n string. So you will need to process this and turn the output into a propper list object first.
The task Gather USER IDs from processes id before killing. is returning a dictionary containing the key results where the value is of type list, so you will need iterate over it and fetch for each element the stdout value.
This is how I solved it.
---
- hosts: "localhost"
gather_facts: true
become: true
tasks:
- name: Set default values
set_fact:
process_ids: []
user_names: []
- name: Get running processes list from remote host
shell: "ps -few | grep java | grep -v grep | awk '{print $2}'"
changed_when: false
register: running_processes
- name: Register a list of Process ids (Split newline from output before)
set_fact:
process_ids: "{{ running_processes.stdout.split('\n') }}"
- name: Gather USER IDs from processes id before killing.
shell: "id -nu `cat /proc/{{ item }}/loginuid`"
register: curr_user_ids
with_items: "{{ process_ids }}"
- name: Register a list of User names (Out of result from before)
set_fact:
user_names: "{{ user_names + [item.stdout] | unique }}"
when: item.rc == 0
with_items:
- "{{ curr_user_ids.results }}"
- name: Set unique entries in User names list
set_fact:
user_names: "{{ user_names | unique }}"
- name: DEBUG
debug:
msg: "{{ user_names }}"
The variable curr_user_ids registers results of each iteration
register: curr_user_ids
with_items: "{{ running_processes.stdout_lines }}"
The list of the results is stored in
curr_user_ids.results
Take a look at the variable
- debug:
var: curr_user_ids
and loop the stdout_lines
- debug:
var: item.stdout_lines
loop: "{{ curr_user_ids.results }}"

Ansible mount module to just check state and not report status

Team,
I am writing a validation task that is supposed to just check if a mount exists or not and report its state from output. so my task is below but it fails and am not sure how to handle it. any hint what adjustments do i need to make?
- name: "Verify LVP Mounts on CPU Nodes for mount_device"
shell: "mount | grep sdd"
register: lvp_mount
delegate_to: "{{ item }}"
with_items: "{{ groups['kube-cpu-node'] }}"
#failed_when: lvp_mount.rc != 0
#ignore_errors: yes
# - debug:
# var: lvp_mount
- name: "Report status of mounts"
fail:
msg: |
Mounts sdd not found
Output of `mount | grep sdd`:
{{ lvp_mount.stdout }}
{{ lvp_mount.stderr }}
when: lvp_mount | failed
changed: [localhost -> ] => (item=hostA)
[WARNING]: Consider using the mount module rather than running 'mount'. If you
need to use command because mount is insufficient you can add 'warn: false' to
this command task or set 'command_warnings=False' in ansible.cfg to get rid of
this message.
failed: [localhost -> hostA.test.net] (item=hostA) => {"ansible_loop_var": "item", "changed": true, "cmd": "mount | grep sdd", "delta": "0:00:00.009284", "end": "2019-11-06 18:22:56.138007", "failed_when_result": true, "item": "hostA", "msg": "non-zero return code", "rc": 1, "start": "2019-11-06 18:22:56.128723", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [services-pre-install-checks : Report status of mounts] ************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout'\n\nThe error appears to be in '/home/run_ansible_playbook/k8s/baremetal/roles/services-pre-install-checks/tasks/main.yml': line 265, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: \"Report status of mounts\"\n ^ here\n"}
Your task "Verify LVP Mounts on CPU Nodes for mount_device" is a loop so the register behavior is modified as specified in the documentation.
You can access the various outputs with lvp_mount.results.X.stdout where X is the index.
There is a cleaner way to write your script however. More specifically using:
delegate_to: "{{ item }}"
with_items: "{{ groups['kube-cpu-node'] }}"
is bad practice. You can accomplish your desired outcome at the play level.
For example:
- hosts: kube-cpu-node # allows you to iterate over all hosts in kube-cpu-node group
tasks:
- name: "Verify LVP Mounts on CPU Nodes for mount_device"
shell: "mount | grep sdd"
register: lvp_mount
ignore_errors: yes
# notice there is no loop here
- name: "Report status of mounts"
fail:
msg: |
Mounts sdd not found
Output of `mount | grep sdd`:
{{ lvp_mount.stdout }} # no loop so you can use lvp_mount.stdout
{{ lvp_mount.stderr }} # no loop so you can use lvp_mount.stderr
when: lvp_mount | failed

Ansible: How to run command with shell output

Self explanatory. I want to link based on $(which {{ item }}).
Already saw the register function, but as I need to do a nested loop I'm not sure how to use it.
name: Link bins to user path
command: 'ln -s \$(which {{ item.1 }}) /home/{{ item.0 }}/bin/{{ item.1 }}'
with_nested:
- "{{ jail_users }}"
- "{{ jail_user_commands }}
Output:
failed: [rousertest] (item=[u'bob', u'date']) => {"changed": true,
"cmd": ["ln", "-s", "$(which", "date)", "/home/bob/bin/date"], "delta":
"0:00:00.011825", "end": "2019-07-11 08:17:32.921705", "item": ["bob", "date"], "msg": "non-zero return code", "rc": 1, "start": "2019-07-11
08:17:32.909880", "stderr": "ln: target ‘/home/bob/bin/date’ is not a
directory", "stderr_lines": ["ln: target ‘/home/bob/bin/date’ is not a
directory"], "stdout": "", "stdout_lines": []
Of course I was expecting something like this:
sudo ansible server -i inventory -m shell -a 'echo $(which date)'
rousertest | SUCCESS | rc=0 >>
/usr/bin/date
Below is the play. Avoid using command module for link. Use file module with state=link.
- name: Link binary
hosts: all
gather_facts: true
vars:
files:
- date
- ls
users:
- user1
- user2
tasks:
- name: Find paths
command: which {{ item }}
with_items:
- "{{ files }}"
register: result
- name: Link bins to user path
file:
src: "{{ item.1.stdout }}"
dest: "/home/{{ item.0 }}/bin/{{ item.1.item }}"
owner: "{{ item.0 }}"
group: "{{ item.0 }}"
state: link
with_nested:
- "{{ users }}"
- "{{ result.results }}"

Not able to gather facts of ansible host machine

Set up module in ansible gives an error when i tried to set custom facts on host machine using control machine
---
- hosts: test-servers
gather_facts: false
tasks:
- name: deleting Facts directory
file:
path: /etc/ansible/facts.d/
state: absent
- name: Creates a directiory
file:
path: /etc/ansible/facts.d/
recurse: yes
state: directory
- name: Copy custom date facts to host machine
copy:
src: /app/ansible_poc/roles/custom_facts/templates/facts.d/getdate.fact
dest: /etc/ansible/facts.d/getdate.fact
mode: 0755
- name: Copy custom role facts to host machine
copy:
src: /app/ansible_poc/roles/custom_facts/templates/facts.d/getrole.fact
dest: /etc/ansible/facts.d/getrole.fact
mode: 0755
- name: Reloading facts
setup:
- name: Display message
debug:
msg: "{{ ansible_local.getdate.date.date }}"
- name: Display message
debug:
msg: "{{ ansible_local.getrole.role.role }}"
I get following error when i tried to collect facts of ansible host machine. I have set up a file getdate.fact and getrole.fact which has code respectively
#############getdate.fact###############
echo [date]
echo date= `date`
########################################
#############getrole.fact###############
echo [role]
echo role= `whoami`
########################################
and when i tried to run the playbook main.yml then it following error.
[root#ansibletower tasks]# ansible -m setup test-servers
192.168.111.28 | FAILED! => {
"changed": false,
"cmd": "/etc/ansible/facts.d/getdate.fact",
"msg": "[Errno 8] Exec format error",
"rc": 8
}
192.168.111.27 | FAILED! => {
"changed": false,
"cmd": "/etc/ansible/facts.d/getdate.fact",
"msg": "[Errno 8] Exec format error",
"rc": 8
}
If I recall correctly, executables are expected to return JSON:
#!/bin/bash
echo '{ "date" : "'$( date )'" }'
You probably need to add "shebang" line to your fact scripts. I.e., getdate.fact should look like:
#!/bin/sh
echo [date]
echo date=`date`

How can I use the mv module Ansible

I am trying to use the mv module on Ansible but I am not having luck.
In my initial attempt I did the following:
- name: changing the name of the file
shell: mv /tmp/bundle /opt/Rocket.Chat
And I get the following error:
FAILED! => {"changed": true, "cmd": "mv /tmp/bundle /opt/Rocket.Chat", "delta": "0:00:00.033553", "end": "2019-02-11 06:06:43.273787", "msg": "non-zero return code", "rc": 1, "start": "2019-02-11 06:06:43.240234", "stderr": "mv: cannot move ‘/tmp/bundle’ to ‘/opt/Rocket.Chat/bundle’: File exists", "stderr_lines": ["mv: cannot move ‘/tmp/bundle’ to ‘/opt/Rocket.Chat/bundle’: File exists"], "stdout": "", "stdout_lines": []}
So, I changed it to:
- name: create directory
file:
state: directory
path: "/opt/Rocket.Chat"
- name: copy the files
copy:
src: "/tmp/bundle"
dest: "/opt/Rocket.Chat"
remote_src: yes
- name: delete the other files
file: path=/tmp/bundle state=absent
My new error is:
FAILED! => {"changed": false, "msg": "Remote copy does not support recursive copy of directory: /tmp/bundle"}
Seems that the "copy module to work with recursive and remote_src" does not work yet, but will be supported from May 2019
Here is a workaround, edit the folder names to your setup.
# Copy all files and directories from /usr/share/easy-rsa to /etc/easy-rsa
- name: List files in /usr/share/easy-rsa
find:
path: /usr/share/easy-rsa
recurse: yes
file_type: any
register: find_result
- name: Create the directories
file:
path: "{{ item.path | regex_replace('/usr/share/easy-rsa','/etc/easy-rsa') }}"
state: directory
mode: "{{ item.mode }}"
with_items:
- "{{ find_result.files }}"
when:
- item.isdir
- name: Copy the files
copy:
src: "{{ item.path }}"
dest: "{{ item.path | regex_replace('/usr/share/easy-rsa','/etc/easy-rsa') }}"
remote_src: yes
mode: "{{ item.mode }}"
with_items:
- "{{ find_result.files }}"
when:
- item.isdir == False

Resources