I'm currently creating a possibility to auto-obtain a Letsencrypt certificate using my ansible-playbook.
I'd like to check if the /etc/letsencrypt/domain.tld directory exists, when it doesn't, I need to obtain a certificate.
---
- name: LETSENCRYPT | Checking for existing certificates
stat:
path: /etc/letsencrypt/live/{{ item.value.server_name }}
register: le_cert_exists
with_dict: "{{ sites }}"
when: item.value.letsencrypt | default(false) | bool
- name: DEBUG | Output result of le cert exists
debug:
var: le_cert_exists
- name: LETSENCRYPT | Output sites that need a new certificate
debug:
msg: Obtain certificate here
var: item.item
with_items: le_cert_exists.results
when: item.stat.exists is defined and not item.stat.exists
So far it is working, except for the last function. The last task just keeps getting skipped or fails with the following error:
fatal: [-]: FAILED! => {"msg": "The conditional check 'item.stat.exists is defined and not item.stat.exists' failed. The error was: error while evaluating conditional (item.stat.exists is defined and not item.stat.exists): 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'stat'\n\nThe error appears to have been in '/path/to/main.yml': line 13, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: LETSENCRYPT | Output sites that need a new certificate\n ^ here\n"}
Does anyone has an example of how this could be done easily?
I just need to execute a command when a directory does not exists.
This with_items: le_cert_exists.results is wrong,
this with_items: "{{ le_cert_exists.results }}" is correct.
Related
wondering if anyone can help us with this.
The end goal is to refresh the variables back into the play from a YAML file which was generated previously if the file exists.
I'm using stat to check if the files exist and this works - 'name: Registering if file exists'. If i debug filecheck i can see the 2 entries in the dataset.
Next im trying to reload the vars from the file -final-dataset-file-1 if the file exists using the when condition - filecheck.stat.exists
- name: Registering if file exists
stat:
path: "{{ inventory_dir }}/host_vars/{{ inventory_hostname }}/final-dataset-{{ item }}.yml"
loop:
- file-1
- file-2
register: filecheck
- name: IOS - Refreshing final-dataset variables generated by the above tasks in order to service any subsequent tasks
include_vars:
file: "{{ inventory_dir }}/host_vars/{{ inventory_hostname }}/final-dataset-{{ item }}.yml"
loop:
- file-1
- file-2
when: filecheck.stat.exists
This is the error i'm seeing
fatal: [router]: FAILED! => {"msg": "The conditional check 'filecheck.stat.exists' failed. The error was: error while evaluating conditional (filecheck.stat.exists): 'dict object' has no attribute 'stat'\n\nThe error appears to be in '/ansible/roles/roles_nane/tasks/report.yml': line 94, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: IOS - Refreshing final-dataset variables generated by the above tasks in order to service any subsequent tasks\n ^ here\n"}
Its like we need to loop through filecheck for each file/item and match these against the files that are a part of the include_vars items but i'm not sure how to do this.
Any comments would be appreciated.
Cheers
Iterate the results from the previous task e.g.
- include_vars: "{{ item.stat.path }}"
loop: "{{ filecheck.results }}"
when: item.stat.exists
I'm trying to replicate the first with_item example from ansible docs, but I'm facing this error:
fatal: [user#my-vm]: FAILED! => {"msg": "The task includes an option with an undefined variable.
The error was: 'item' is undefined\n\nThe error appears to be in 'path/ansible/playbooks/android-dev.yml': line 4,
column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n
The offending line appears to be:\n\n tasks:\n - name: Debugging with items\n ^ here\n"}
My code is:
- hosts: test
tasks:
- name: Debugging with items
debug:
msg: "An item: {{ item }}"
with_items:
- 1
- 2
- 3
I'm following the first example of this page to build the task: https://docs.ansible.com/ansible/latest/plugins/lookup/items.html
I've started using ansible now and it may be a simple issue to fix, but I really can't find any solution online
The indentation is wrong. Fix it
- hosts: test
tasks:
- name: Debugging with items
debug:
msg: "An item: {{ item }}"
loop:
- 1
- 2
- 3
Use loop instead of with_items.
Following is the piece of code, which is retrieving list of local zones and trying to enter rescue block if any one of the local zones is not in RUNNING state.
But the rescue block is failing, at 'Check if the zones are in running state'
Expectation is to send an email with the task name. But it is working well with other failed tasks.Can anyone please guide?
FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/etc/ansible/playbooks/misc/test1404.yml': line 23, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n rescue:\n - name: Sending an e-mail from Ansible controller node\n ^ here\n"}
- '{{ host }}'
tasks:
- block:
- name: Retrieve list of local zones
shell: /usr/sbin/zoneadm list | grep -v global
register: lzones
tags:
- local_zone_list
- debug:
msg: "{{ item }}"
with_items: "{{lzones.stdout_lines}}"
- name: Check if the zones are in running state
shell: /usr/sbin/zoneadm list | grep -v global | grep "{{ item }}" | awk '{print$3}'
register: status
with_items: "{{lzones.stdout_lines}}"
failed_when: status.stdout.find('running') == -1
< few other tasks>
rescue:
- name: Sending an e-mail from Ansible controller node
mail:
host: localhost
port: 25
to: xyz#abc.com
subject: Reboot Failed
body: Reboot FAILED at TASK - {{ ansible_failed_task.name }} with ERROR {{ ansible_failed_result }}
delegate_to: localhost
Well that was an absolutely fascinating rabbit hole.
Because in ansible jinja2 templates are rendered recursively, when it tries to render the failed message, which contains the failed template, it tries to re-render the failed template again, re-causing the error
This appears to be impacting you by the inclusion of the ansible_failed_task variable, since -- inexplicably -- it appears to be safe to include ansible_failed_result in the body
As best I can tell by experimenting with ansible 2.9.6, one must determine if it is possible to safely output the a*_task flavor variable before touching it, because I was wholly unable to find any combination of | string or |regex_replace or anything that allowed jinja2 to touch that variable so long as it contains the bogus variable reference:
- block:
- debug:
msg: this explodes {{ nope_not_a_var }}
rescue:
- set_fact:
is_undefined_error: '{{ "undefined variable" in ansible_failed_result.msg }}'
- name: variable is unsafe version
debug:
msg: >-
failed task action has an undefined variable in the task,
so we cannot show you the task, but here is the result: {{ ansible_failed_result }}
when: is_undefined_error
- name: variable is safe to output version
debug:
msg: Reboot FAILED at TASK - {{ ansible_failed_task.name }} with ERROR {{ ansible_failed_result }}
when: not is_undefined_error
It may be safe to inline that test of "..." in ansible_failed_result.msg into the when: lines directly, but since it (should) produce the same answer both times, there's no really good reason to evaluate it twice
This appears to me to be an ansible bug, but I don't have the emotional energy to take it up with their community -- however, I encourage you to file a bug with them
I currently want to select specifically the Windows adapter name ONLY from the ansible facts.
So my problem is that I cannot retrieve this value only.
Ansible 2.8.2_1 with Winrm & Kerberos Authentication are running on the server.
I've tried to launch this playbook :
- hosts: win_clients
gather_facts: true
strategy: free
tasks:
- name: Get Ansible network facts
debug:
msg: "{{ ansible_facts['interfaces'] }}"
and it works fine but I have all the informations about the interfaces. I just want the "connection_name".
When I put this line in the playbook :
msg: "{{ ansible_facts['interfaces']['connection_name'] }}"
It shows this message at the execution :
FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'connection_name'\n\nThe error appears to be in '/home/sopra/git/rnd-windows/automation/playbooks/Dns/test.yaml': line 5, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Get Ansible network facts\n ^ here\n"}
I don't understand because the variable "connection_name" is well defined.
Can somebody help me? Thanks.
Have a good day !
If you want to list the connection_name, use below, as ansible_facts['interfaces'] is an array
- hosts: win_clients
gather_facts: true
strategy: free
tasks:
- name: Get Ansible network facts
debug:
msg: "{{ item.connection_name }}"
with_items:
- "{{ ansible_facts['interfaces'] }}"
Thank you very much for your support. I did resolve my problem.
Basically, my playbook consists in changing the DNS configuration if the occurrence of one (old) DNS's IP if found.
# tasks file for configureDnsServerAddresses
# Get the configuration state about DNS
# If one occurrence of 'old_dnsserver' is found...
- name: Get DNS configuration
win_shell: ipconfig /all | findstr {{ old_dnsserver }}
register: check_old_dns
changed_when: false
# '.rc' means the return code
failed_when: check_old_dns.rc != 0 and check_old_dns.rc != 1
# ... it will be replaced by 2 new ones
- name: Change the DNS only if the IP {{ old_dnsserver }} is found
win_dns_client:
adapter_names: "{{ item.connection_name }}"
ipv4_addresses:
- "{{ dnsserver1 }}"
- "{{ dnsserver2 }}"
# Array based on Ansible facts
with_items:
- "{{ ansible_facts['interfaces'] }}"
# Apply only if 'check_old_dns' is not empty, which means that the old DNS is found
when: check_old_dns.stdout | length > 0
This playbook is role-based, so the variables are stored in a "defaults" folder.
The code mentioned above was intended for testing purposes.
I have an ansible-playbook and when i try to run this playbook i am getting this error
(specified line no longer in file, maybe it changed?)
--
- name: check if the public/private key exist at ~/.ssh/
stat:
path: /root/.ssh/id_rsa.pub
register: st
- name: run the command
command: cat /root/.ssh/id_rsa.pub|ssh -i /root/.ssh/bi_ppc.pem ubuntu#"{{items}" "cat >> .ssh/authorized_keys"
with_items:
- groups['ubuntu']
when: st.changed
~
ansible --version
ansible 2.2.0.0
config file = /home/swathi/Desktop/infrastructure/ansible.cfg
configured module search path = Default w/o overrides
You can use authorized_key module, copy pub key from local to remote.
--
- name: get public key
local_action: shell cat /home/user/.ssh/id_rsa.pub
register: pubkey
- name: check keys
debug: msg="{{ pubkey.stdout }}"
- name: add public key on the remote server
authorized_key: user=root key="{{ item[0] }}"
delegate_to: "{{ item[1] }}"
with_nested:
- "{{ pubkey.stdout }}"
- "{{groups['ubuntu']}}"
I faced the same error message from ansible:
$ ansible-playbook t.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
ERROR! Syntax Error while loading YAML.
found unexpected end of stream
The error appears to be in '/root/ansible/t.yml': line 6, column 1, but may
be elsewhere in the file depending on the exact syntax problem.
(specified line no longer in file, maybe it changed?)
The playbook is:
$ cat t.yml
---
- hosts: localhost
tasks:
- debug:
msg: "unterminated quoted string
In fact there is a YAML syntax error, at the end of the playbook missing a double quote. As it finish the playbook my editor doesn't help me by showing a different color.
Hope that will help someone else.