I am trying to update a XLSX file locally using this module : https://github.com/mohameosam/open_excel
I have succeed to update the XLSX file when running a task without "Conditional Variables". But when I try to run it with "When" variable. It shows error below :
TASK [Update predepchk] ****************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (open_excel) module: when Supported parameters include: attributes, backup, cell_style, content, delimiter, dest, directory_mode, follow, force, group, index_by_name, mode, op, owner, read_range, regexp, remote_src, selevel, serole, setype, seuser, sheet_name, src, unsafe_writes, updates_matrix"}
Here is my ansible yml file :
---
- hosts: all
tasks:
- name: Ping all hosts
ping:
- name: Print a message
debug:
msg: 'All set'
- name: Show facts available on the system
ansible.builtin.debug:
var: ansible_facts
- name: PredepCHK
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Update predepchk
open_excel:
src: "/root/Documents/Ansible/XLSX/predepchk.xlsx"
dest: "/root/Documents/Ansible/XLSX/predepchk_updated.xlsx"
sheet_name: "predepchk"
op: "w"
updates_matrix: "{{ [{'cell_row': 21, 'cell_col': 1, 'cell_value': 1}] }}"
when: ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "9"
My question will be:
Can I pass this remote host condition to my local tasks?
As answered by #Zeitounator .
It's because I have my when: conditional statement where was not the same level as "name: / open_excel:"
Related
I am executing a PS script on a windows host and want to store its stdout in a file on an ansible local machine. I have a playbook like following:
---
- name: Check Antivirus software
hosts: all
become: false
gather_facts: no
tasks:
- name: Get AV details
win_shell: |
echo "script printing data on stdout"
register: result
- name: save response
copy:
content: '{{ result.stdout }}'
dest: '{{ response_file }}'
delegate_to: localhost
From the above playbook, 1st task gets executed without any issues. But 2nd task gives the following error.
TASK [save response] *******************************************************************************************************************************************
fatal: [20.15.102.192 -> localhost]: UNREACHABLE! => {"changed": false, "msg": "ntlm: HTTPSConnectionPool(host='localhost', port=5986): Max retries exceeded with url: /wsman (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f4940760208>: Failed to establish a new connection: [Errno 111] Connection refused',))", "unreachable": true}
I also tried local_action which is also giving the same error.
I am trying to enhance my playbook by storing the hostname of the changed machines locally, and I want to use as much as possible of the ansible module that is why I choosed the usage of th copy module for this storage:
My playbook look like this :
- name: test connectivity
hosts: all
tasks:
- name: ping
ping:
- name: change default gateway address
replace:
path: /etc/network/interfaces
regexp: '(up route add default gw [\d]*\.[\d]*.[\d]*)\.[\d]*$'
replace: '\1.254'
backup: yes
when: (ansible_facts['distribution'] == "Debian")
- name: restart networking service
service:
name: networking
state: restarted
when: (ansible_facts['distribution'] == "Debian")
- name: change default gateway address on Redhat
replace:
path: /etc/sysconfig/network-scripts/ifcfg-eth0
regexp: '(GATEWAY=[\d]*\.[\d]*.[\d]*)\.[\d]*$'
replace: '\1.254'
backup: yes
when: (ansible_facts['distribution'] == "RedHat")
- name: restart networking service for Redhat
service:
name: network
state: restarted
when: (ansible_facts['distribution'] == "RedHat")
- name: register changed hosts locally
copy:
content: "{{ ansible_facts['hostname'] }}"
dest: "/tmp/changed.txt"
delegate_to: localhost
but the following error keep on popping :
TASK [register changed hosts locally] *******************************************************************************************************************************************************************************************************
fatal: [name of host 1]: FAILED! => {"changed": false, "checksum": "df1496ad2c4ffed5abfad0a9fc69f7fb3a039765", "msg": "Unsupported parameters for (copy) module: delegate_to Supported parameters include: _original_basename, attributes, backup, checksum, content, delimiter, dest, directory_mode, follow, force, group, local_follow, mode, owner, regexp, remote_src, selevel, serole, setype, seuser, src, unsafe_writes, validate"}
fatal: [name of host 2]: FAILED! => {"changed": false, "checksum": "b75217f7ab69a82dd5aea389fcd8eacee15743e5", "msg": "Unsupported parameters for (copy) module: delegate_to Supported parameters include: _original_basename, attributes, backup, checksum, content, delimiter, dest, directory_mode, follow, force, group, local_follow, mode, owner, regexp, remote_src, selevel, serole, setype, seuser, src, unsafe_writes, validate"}
so I want to know is it due to the copy parameters I use if yes? which one exactly ?
- name: register changed hosts locally
copy:
content: "{{ ansible_facts['hostname'] }}"
dest: "/tmp/changed.txt"
delegate_to: localhost
delegate_to option needs to be under copy.
Alternatively see remote_src option https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html#parameter-remote_src
here's what I did to make it work :
- name: log the changed hosts
local_action:
module : lineinfile
line: "{{ ansible_facts['hostname'] }} {{item}}"
dest: /tmp/changed.txt
with_items:
- "{{debresult}}"
- "{{redresult}}"
I'm trying to get a playbook to copy a different set of files to a server, depending an a flag set on the group it belongs too in the ansible inventory.
The code is as follows
- name: check if they exist already
stat:
path: /home/me/set1files
register: st
- name: copy pre-prod if they don't
copy:
src: /home/me/set1files
dest: /home/me
owner: me
group: me
mode: "0644"
when: (st.stat.exists==false) and (is_emms_pp==true)
- name: check if prod files exist
stat:
path: /home/me/set2files
register: stprod
- name: copy prod files
copy:
src: /home/me/set2files
dest: /home/me
owner: me
group: me
mode: "0644"
when: (stprod.stat.exists==false) and (is_emms_pp==false)
and in the inventory file
[PPEMMS]
emmspp1
emmspp2
emmspp3
[PPEMMS:vars]
is_emms_pp = true
[PRODEMMS]
emms1
emms2
emms3
[PRODEMMS:vars]
is_emms_pp = false
[EMMS:children]
PPEMMS
PRODEMMS
When I run the script on a new PP machine, it all seems to work fine, but when I run it on a new Prod machine, it still copies the PP files and skips the step for the Prod machine.
Is this a valid test or do I have something wrong?
One thought I had was that because I'm limiting the script to one machine, rather than the group, its not picking up the group_var?
I'm using the script as
ansible-playbook -i inventory/hosts -l emms1 install_emms.yml --ask-vault-pass --extra-vars '#passwd.yml'
For each machine.
The variable is_emms_pp = true is a string. Quoting from Defining variables at runtime
"Values passed in using the key=value syntax are interpreted as strings. Use the JSON format if you need to pass non-string values such as Booleans, integers, floats, lists, and so on."
Given the inventory to simplify the test
test_01 is_emms_pp=true
test_02 is_emms_pp=false
The playbook
- hosts: test_01,test_02
tasks:
- debug:
var: is_emms_pp|type_debug
gives
ok: [test_01] =>
is_emms_pp|type_debug: str
ok: [test_02] =>
is_emms_pp|type_debug: str
Comparison between a string and a boolean will fail
- debug:
msg: Copy file
when: is_emms_pp == true
gives
skipping: [test_01]
skipping: [test_02]
One option is to compare strings. The task below works as expected
- debug:
msg: Copy file
when: is_emms_pp == 'true'
gives
ok: [test_01] =>
msg: Copy file
skipping: [test_02]
The cleaner option is to convert the variable to boolean. The task below gives the same result
- debug:
msg: Copy file
when: is_emms_pp|bool
See CONDITIONAL_BARE_VARS
Example of how to fix the conditions
- name: check if they exist already
stat:
path: /home/me/set1files
register: st
- name: copy pre-prod if they don't
debug:
msg: Copy set1files
when:
- not st.stat.exists
- is_emms_pp|bool
- name: check if prod files exist
stat:
path: /home/me/set2files
register: st
- name: copy prod files
debug:
msg: Copy set2files
when:
- not st.stat.exists
- not is_emms_pp|bool
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`
I have to run an ansible playbook to execute the following tasks
1) Calculate date in YYYY_MM_DD format and then use this prefix to download some file from aws to my local machine. The filename is of the following format 2015_06_04_latest_file.csv
2) I have to then create a folder by the name 2015_06_04 into multiple hosts and upload this file there.
This is my current playbook -
---
- hosts: 127.0.0.1
connection: local
sudo: yes
gather_facts: no
tasks:
- name: calculate date
shell: date "+%Y_%m_%d" --date="1 days ago"
register: output
- name: set date variable
set_fact: latest_date={{ item }}
with_items: output.stdout_lines
- local_action: command mkdir -p /tmp/latest_contracts/{{ latest_date }}
- local_action: command /root/bin/aws s3 cp s3://primarydatafolder/data/{{ latest_date }}_latest_data.csv /tmp/latest_contracts/{{ latest_date }}/ creates=/tmp/latest_contracts/{{ latest_date }}/latest_data.csv
register: result
ignore_errors: true
- local_action: command /root/bin/aws s3 cp s3://secondarydatafolder/data/{{ latest_date }}_latest_data.csv /tmp/latest_contracts/{{ latest_date }}/ creates=/tmp/latest_contracts/{{ latest_date }}/latest_data.csv
when: result|failed
# remove the date prefix from the downloaded file
- local_action: command ./rename_date.sh {{ latest_date }}
ignore_errors: true
- hosts: contractsServers
sudo: yes
gather_facts: no
tasks:
- name: create directory
file: path={{item.path}} state=directory mode=0775 owner=root group=root
with_items:
- {path: '/var/mukul/contracts/{{ latest_date }}' }
- {path: '/var/mukul/contracts/dummy' }
- name: copy dummy contracts
copy: src=dummy dest=/var/mukul/contracts/
- name: delete previous symlink
shell: unlink /var/mukul/contracts/latest
ignore_errors: true
- name: upload the newly created latest date folder to the host
copy: src=/tmp/latest_contracts/{{ latest_date }} dest=/var/mukul/contracts/
- name: create a symbolic link to the folder on the host and call it latest
action: file state=link src=/var/mukul/contracts/{{ latest_date }} dest=/var/mukul/contracts/latest
As per ansible's documentation on set_fact variable, this variable latest_date should be available across plays. However, ansible fails with the following message
failed: [192.168.101.177] => (item={'path': u'/var/mukul/contracts/{# latest_date #}'}) => {"failed": true, "item": {"path": "/var/mukul/contracts/{# latest_date #}"}}
msg: this module requires key=value arguments (['path=/var/mukul/contracts/{#', 'latest_date', '#}', 'state=directory', 'mode=0775', 'owner=root', 'group=root'])
It looks as if the second playbook is unable to get the value of the latest_date fact. Can you please tell me where i'm making a mistake?
Facts are host specific. As the documentation about set_fact says, "[v]ariables [set with set_fact] are set on a host-by-host basis".
Instead, I'd try using run_once as defined in Delegation, rolling updates, and local actions, like this:
- hosts: contractsServers
tasks:
- name: Determine date
local_action: shell: date "+%Y_%m_%d" --date="1 days ago"
register: yesterday
always_run: True
changed_when: False
run_once: True
- name: Do something else locally
local_action: ...
register: some_variable_name
always_run: True
changed_when: False
run_once: True
- name: Do something remotely using the variables registered above
...
You could enable fact-caching. You will need to set up a local redis instance where facts then will be stored.