Ansible - 'block' is not a valid attribute for a Play - ansible

I'm trying to figure out how to resolve the Error message: ERROR! 'block' is not a valid attribute for a Play
How do I achieve this? I'm trying to use the "block" condition, but it's not working. I'm not sure what to search anymore.
Code:
---
- name: Get diagnostic info block
block:
- name: Get top process diagnostic info
script: library/diag_top_processes.ps1
failed_when: false
changed_when: false
register: diag_top_proc_out
- name: Get memory and pagefile usage diagnostic info
script: library/diag_memory_and_pagefile.ps1
failed_when: false
changed_when: false
register: diag_mem_page_out
- name: Get CPU info
script: library/diag_cpu_info.ps1
failed_when: false
changed_when: false
register: diag_cpu_info_out
- name: Init diag message
set_fact:
diag_msg: "Diagnostic information:"
proc_info:
"{{ diag_top_proc_out.stdout|regex_replace('\r\n|\n|\r', '') }}"
cpu_info: "{{ diag_cpu_info_out.stdout_lines | join(' ') }}"
- name: Add top process info
set_fact:
diag_msg: "{{ [diag_msg, proc_info] | join(' ') }}"
- name: Add memory info
set_fact:
diag_msg:
"{{ [diag_msg, diag_mem_page_out.stdout_lines[0]] | join(' ') }}"
- name: Add CPU info
set_fact:
diag_msg:
"{{ [diag_msg, cpu_info] | join(' ') }}"
rescue:
- name: Diag info collection failed, setup variable
set_fact:
diag_failed: true
Error using 'block' for a Play:
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
ERROR! 'block' is not a valid attribute for a Play
The error appears to be in '/home/keith/Ansible/ansible-role-high-cpu-usage-win/tasks/get_diagnostic.yml': line 3, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Get diagnostic info block
^ here

This file only correct if you do
- include_tasks path/to/get_diagnostic.yml
As lopez said, it cannot be called with ansible-playbook command line.

Rewrite play as:
---
- name: Play
tasks:
- name: Get diagnostic info block
block:
- name: Get top process diagnostic info
script: library/diag_top_processes.ps1
failed_when: false
changed_when: false
register: diag_top_proc_out
....
rescue:
- name: Another tasks
....

Related

How to register and capture only the output that meets a failed condition criteria in ansible playbook?

I am trying to set up a playbook as follows where I need to send an email notification when my task fails. The alert with email notification as such works as expected, however I am unable to capture the output just for the failed conditions and currently the way I am registering gives me all results including the variables (file paths in this example) where the condition does not fail.
---
- hosts: test-box
tasks:
- name: alert on failure
block:
- name: generate a list of desired file paths
find:
paths: /base/sdir
recurse: yes
file_type: file
patterns: "abrn.*.dat"
use_regex: yes
register: file_paths
- name: check if file stopped updating
vars:
msg: |
"{{ item }}"
"{{ ansible_date_time.epoch }}"
"{{ item.stat.mtime|int }}"
"{{ ( (ansible_date_time.epoch|int - item.stat.mtime|int) / 60 ) | int }} min"
with_items: "{{ ts.results }}"
fail:
msg: |
"{{ msg.split('\n') }}"
register: failed_items ### -> HOW TO REGISTER ONLY THE FILE PATHS (RESULTS) WHERE THIS FAIL CONDITION IS MET??
when: ( (ansible_date_time.epoch|int - item.stat.mtime|int) / 60 ) | int > 2
rescue:
- name: email notification
mail:
host: localhost
port: 25
from: A
to: B
subject: TASK FAILED
body: |
Failed subdirs: {{ failed_items }} ## This gives me all results including those where the failed condition is not met
delegate_to: localhost
...
In the body of the email, I want to capture only the file paths where the mtime condition is met but currently I get all file paths.
Any suggestions on how I can filter to capture the output only for matching condition?
Thanks.
You should use set_fact, this way you will assign a list variable only if your when condition is true.
---
- hosts: localhost
become: false
vars:
path: "{{ '%s/bin' | format(lookup('env', 'HOME')) }}"
time: "{{ 2 * 60 }}" # 2 mins
tasks:
- name: Find files in a defined path
find:
paths: "{{ path }}"
register: _result
- name: Add files not modified for longer time than defined to list
set_fact:
stale_files: "{{ stale_files | default([]) + [item.path] }}"
loop: "{{ _result.files }}"
when: ((ansible_date_time.epoch | float) - item.mtime) > (time | float)
- name: Show stale files
debug:
msg: "{{ stale_files }}"
Well you could use also another approach, ie. make loop with filtering (for me selectattr filter did not work with lt test, thus json_query filter should work, see Can't compare attribute to a number. Error: "not supported between instances of 'AnsibleUnsafeText' and 'int'").

detect file difference (change) with `ansible`

In this task I found a roundabout method to compare two files (dconfDump and dconfDumpLocalCurrent) and to set a variable (previously defined as false) to true if the two files differ.
The solution seem to work, but it looks ugly and, as a beginner with ansible, I have the impression a better solution should be existing.
---
# vars file for dconfLoad
local_changed : false
target_changed : false
---
- name: local changed is true when previous target different then local current
shell: diff /home/frank/dconfDump /home/frank/dconfDumpLocalCurrent
register: diff_oldtarget_localCurrent
register: local_changed
ignore_errors: true
- debug:
msg: CHANGED LOCALLY
when: local_changed
Some background to the task, which is an attempt to synchronize files: A file LocalCurrent is compared with LocalOld and CurrentTarget, to determine if the LocalCurrent is changed and if it is different than currentTarget. If LocalCurrent is not changed and CurrentTarget is changed, then apply the change (and set LocalOld to CurrentTarget); if LocalCurrent is changed then upload to controller.
What is the appropriate approach with ansible? Thank you for help!
You can use stat to get the checksum and then compare it. Please see below.
tasks:
- name: Stat of dconfDump
stat:
path : "/tmp/dconfDump"
register: dump
- name: SHA1 of dconfDump
set_fact:
dump_sha1: "{{ dump.stat.checksum }}"
- name: Stat of dconfDumpLocalCurrent
stat:
path : "/tmp/dconfDumpLocalCurrent"
register: dump_local
- name: SHA1 of dconfDumpLocalCurrent
set_fact:
local_sha1: "{{ dump_local.stat.checksum }}"
- name: Same
set_fact:
val: "False"
when: dump_sha1 != local_sha1
- name: Different
set_fact:
val: "True"
when: dump_sha1 == local_sha1
- name: Print
debug:
msg: "{{val}}"
Use stat and create dictionary of checksums. For example
- stat:
path: "{{ item }}"
loop:
- LocalOld
- LocalCurrent
- CurrentTarget
register: result
- set_fact:
my_files: "{{ dict(paths|zip(chkms)) }}"
vars:
paths: "{{ result.results|map(attribute='stat.path')|list }}"
chkms: "{{ result.results|map(attribute='stat.checksum')|list }}"
- debug:
var: my_files
gives (abridged) if all files are the same
my_files:
CurrentTarget: 7c73e9f589ca1f0a1372aa4cd6944feec459c4a8
LocalCurrent: 7c73e9f589ca1f0a1372aa4cd6944feec459c4a8
LocalOld: 7c73e9f589ca1f0a1372aa4cd6944feec459c4a8
Then use the dictionary to compare the checksums and copy files. For example
# If LocalCurrent is not changed and CurrentTarget is changed,
# then apply the change (and set LocalOld to CurrentTarget)
- debug:
msg: Set LocalOld to CurrentTarget
when:
- my_files['LocalCurrent'] == my_files['LocalOld']
- my_files['LocalCurrent'] != my_files['CurrentTarget']
- debug:
msg: Do not copy anything
when:
- my_files['LocalCurrent'] == my_files['LocalOld']
- my_files['LocalCurrent'] == my_files['CurrentTarget']
gives
TASK [debug] ****
skipping: [localhost]
TASK [debug] ****
ok: [localhost] =>
msg: Do not copy anything

Playbook is getting hanged for some time and resuming itself after that

When i used WHEN condition for block which contains a lot of tasks the playbook is getting stuck before entering into that block and staying in the hung state for a longtime.
i have added ANSIBLE_SSH_PIPELINING=True in ansible.cfg, but it's not working.
- block:
- block:
- name: Interface Status Details
include: interface_details.yml
register: result
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout }}
- debug: var=LowerCaseResult
- block:
- name: Calling Dependency Playbook
include: one_test.yml
register: result
- debug: var=result
when: "'is up' in LowerCaseResult"
- block:
- name: Calling Dependency Playbook
include: two_test.yml
register: cmd_result
- debug: var= cmd_result
when: "'is up' not in LowerCaseResult"
when: true
Debug is not printing the playbook is getting stuck for a long time no error message is produced.
(ansible 2.7.9)
ansible-lint does not complain about nested block (interesting!) See nested blocks lose conditions on parent blocks #12395 (ansible locked and limited conversation to collaborators on Apr 25) This might cause problems until resolved.
Problems in the code
1) Nothing is registered by include use include_tasks
- name: Interface Status Details
include_tasks: interface_details.yml
register: result
2) The closing quotation is missing; If there is no stdout in this result the task will fail
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout }}
correct, set default to 'is NOT up'
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout|default('is NOT up') }}"
3) Extra space after var=
- debug: var= cmd_result
correct
- debug: var=cmd_result
The play below might be working
- hosts: localhost
tasks:
- block:
- block:
- name: Interface Status Details
include_tasks: interface_details.yml
register: result
- debug: var=result
- name: Interface Result Global
set_fact:
LowerCaseResult: "{{ result.stdout|default('is NOT up') }}"
- debug: var=LowerCaseResult
- block:
- name: Calling Dependency Playbook
include_tasks: one_test.yml
register: result
- debug: var=result
when: "'is up' in LowerCaseResult"
- block:
- name: Calling Dependency Playbook
include_tasks: two_test.yml
register: cmd_result
- debug: var=cmd_result
when: "'is up' not in LowerCaseResult"
when: true

Registering multiple variables in a loop

I have a variable yaml file:
---
apps:
- client
- node
- gateway
- ic
- consul
and this task:
- name: register if apps exists
stat: path="/etc/init.d/{{ item }}"
with_items: apps
register: "{{ item.stat.exists }}exists"
I need to end up with a variable for each app with a value of true or false whether the file exists or not:
clientexists = true
nodeexists = true
gatewayexists = false
icexists = true
consulexists = false
For some reason, the item and exists concat is not working.
How can I achieve that??
Try this hope this will help you out. While looping in Stats.yml then msg field will contain your desired output.
Variables.yml Here we are defining variables
---
apps:
- client
- node
- gateway
- ic
- consul
Stats.yml
---
- hosts: localhost
name: Gathering facts
vars_files:
- /path/to/variables.yml
tasks:
- name: "Here we are printing variables"
debug:
msg: "{{apps}}"
- name: "Here we are gathering stats and registering it"
stat:
path: "/etc/init.d/{{item}}"
register: folder_stats
with_items:
- "{{apps}}"
- name: "Looping over registered variables, Its msg field will contain desired output"
debug:
msg: "{{item.invocation.module_args.path}}: {{item.stat.exists}}"
with_items:
- "{{folder_stats.results}}"
...
folder_stats will contain whole result, for individually referring to single - single result You can use it like this in you playbook.
folder_stats.results[0].stat.exists
folder_stats.results[1].stat.exists
folder_stats.results[2].stat.exists
folder_stats.results[3].stat.exists

Saving state of services in Linux services in Ansible

I am trying to save whether services are in running state or stopped. I applied the following login.
---
- hosts: all
vars:
myName: Nikunj
result: ""
tasks:
- name: Initialize empty Started and Stopped list of strings
set_fact:
started: []
stopped: []
- name: Saving context of the VM
shell: service tomcat status
ignore_errors: true
register: result
when: ' "running" in "{{result.stdout}}" '
set_fact:
started : "{{ started }} + ['tomcat']"
- debug:
msg: "{{started}}"
shell command here is giving me eroor.
---
- hosts: all
vars:
myName: Nikunj
result: ""
tasks:
- name: Initialize empty Started and Stopped list of strings
set_fact:
started: []
stopped: []
- name: Saving context of the VM
shell: service tomcat status
ignore_errors: true
register: result
- name: setting fact
set_fact:
started : "{{ started }} + ['tomcat']"
when: ' "running" in "{{result.stdout}}" '
- debug:
msg: "{{started}}"
This will work. set_fact is an individual module.

Resources