ERROR: tasks is not a legal parameter - Ansible playbook - ansible

In my playbook I have a conditional include statement to include a task:
tasks:
# Install Java if not present
- name: Execute Java
shell: java -version
register: result
ignore_errors: True
- include: tasks/java.yml
when: result | failed
...
When I execute playbook it give out an error:
user1#localhost:~ ansible-playbook tomcat.yml
ERROR: tasks is not a legal parameter in an Ansible task or handler
However when I replace this include statement with shell or something else, playbook runs as expected....
Ansible docs tells that task can be conditionally included, so why I am getting error here?

Solution: You should leave out the "tasks:" part in the included file.
Why it fails:
When you include, you are already in the tasks section so to Ansible it looks like:
- tasks:
tasks:
- name: https://www.digitalocean.com/pricing/
...

This happens when you define "tasks" within "tasks"
Tasks definitions within tasks definitions can happen if you try to include another playbook that has a tasks definition in it.

Related

How to run tasks file as a playbook and as an include_file

I have a generic tasks, like update a DNS records based on my machine -> server
Which I use it in my playbooks with include_tasks like so:
- name: (include) Update DNS
include_tasks: task_update_dns.yml
I have many of these "generic tasks" simply acting as a "shared task" in many playbooks.
But in some cases, I just want to run one of these generic tasks on a server, but running the following gives the below error:
ansible-playbook playbooks/task_update_dns.yml --limit $myserver
# ERROR
ERROR! 'set_fact' is not a valid attribute for a Play
Simply because it's not a "playbook" they are just "tasks"
File: playbooks/task_update_dns.yml
---
- name: dig mydomain.com
set_fact:
my_hosts: '{{ lookup("dig", "mydomain.com").split(",") }}'
tags: always
- name: Set entries
blockinfile:
....
I know I can write a playbook, empty, that only "include" the task file, but I don't want to create a shallow playbook now for each task.
Is there a way to configure the task file in such way that I'll be able to run it for both include_tasks and as a "stand alone"/play command line ?
Have you tried to use custom tags for those tasks?
Create a playbook with all the tasks
---
- name: Update web servers
hosts: webservers
remote_user: root
tasks:
- name: dig mydomain.com
set_fact:
my_hosts: '{{ lookup("dig", "mydomain.com").split(",") }}'
tags: always
- name: Set entries
blockinfile:
tags:
- set_entries
- name: (include) Update DNS
include_tasks: task_update_dns_2.yml
tags:
- dns
...
when you need to run only that specific task, you just need to add the --tag parameter in the execution with the task name
ansible-playbook playbooks/task_update_dns.yml --limit $myserver --tag set_entries

How to call a taggued tasks on only one role in a playbook?

I have a playbook than lauches multiple rĂ´les, one of them manage the install and the uninstall of sophos antivirus. It can handle the installation or the unistallation using tags but musn't obviously do booth a the same time.
So my question is how can I lanch just this role in the playbook with the tag install without overloading all the tasks inside this role? I just want to execute only the taggued task, as the intended use for the tasks in general.
I've tried a few syntax but none seems to work, it always overload all the tasks with the tag instead of executing the taggued tasks:
roles:
- role: ../roles/repos.linux
- role: ../roles/sophos
tags: [install,check]
or roles:
- role: ../roles/repos.linux
- {role: ../roles/sophos, tags: install,check}
Expected:
The role execute only the taggued tasks called
Actual:
Every task is overloaded with the tags I try to execute
Use include_role. For example:
tasks:
- include_role:
name: repos.linux
apply:
tags:
- install
- check

Error while using vars_prompt in ansible playbook [duplicate]

Ansible shows an error:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
What is wrong?
The exact transcript is:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
The error appears to have been in 'playbook.yml': line 10, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
---
- name: My task name
^ here
Reason #1
You are using an older version of Ansible which did not have the module you try to run.
How to check it?
Open the list of modules module documentation and find the documentation page for your module.
Read the header at the top of the page - it usually shows the Ansible version in which the module was introduced. For example:
New in version 2.2.
Ensure you are running the specified version of Ansible or later. Run:
ansible-playbook --version
And check the output. It should show something like:
ansible-playbook 2.4.1.0
Reason #2
You tried to write a role and put a playbook in my_role/tasks/main.yml.
The tasks/main.yml file should contain only a list of tasks. If you specified:
---
- name: Configure servers
hosts: my_hosts
tasks:
- name: My first task
my_module:
parameter1: value1
Ansible tries to find an action module named hosts and an action module named tasks. It doesn't, so it throws an error.
Solution: specify only a list of tasks in the tasks/main.yml file:
---
- name: My first task
my_module:
parameter1: value1
Reason #3
The action module name is misspelled.
This is pretty obvious, but overlooked. If you use incorrect module name, for example users instead of user, Ansible will report "no action detected in task".
Ansible was designed as a highly extensible system. It does not have a limited set of modules which you can run and it cannot check "in advance" the spelling of each action module.
In fact you can write and then specify your own module named qLQn1BHxzirz and Ansible has to respect that. As it is an interpreted language, it "discovers" the error only when trying to execute the task.
Reason #4
You are trying to execute a module not distributed with Ansible.
The action module name is correct, but it is not a standard module distributed with Ansible.
If you are using a module provided by a third party - a vendor of software/hardware or another module shared publicly, you must first download the module and place it in appropriate directory.
You can place it either in modules subdirectory of the playbook or in a common path.
Ansible looks ANSIBLE_LIBRARY or the --module-path command line argument.
To check what paths are valid, run:
ansible-playbook --version
and check the value of:
configured module search path =
Ansible version 2.4 and later should provide a list of paths.
Reason #5
You really don't have any action inside the task.
The task must have some action module defined. The following example is not valid:
- name: My task
become: true
I can't really improve upon #techraf answer https://stackoverflow.com/a/47159200/619760.
I wanted to add reason #6 my special case
Reason #6
Incorrectly using roles: to import/include roles as a subtask.
This does not work, you can not include roles in this way as subtasks in a play.
---
- hosts: somehosts
tasks:
- name: include somerole
roles:
- somerole
Use include_role
According to the documentation
you can now use roles inline with any other tasks using import_role or include_role:
- hosts: webservers
tasks:
- debug:
msg: "before we run our role"
- import_role:
name: example
- include_role:
name: example
- debug:
msg: "after we ran our role"
Put the roles at the right place inline with hosts
Include the roles at the top
---
- hosts: somehosts
roles:
- somerole
tasks:
- name: some static task
import_role:
name: somerole
hosts: some host
- include_role:
name: example
You need to understand the difference between import/include static/dynamic
I got this error when I referenced the debug task as ansible.builtin.debug
Causes a syntax failure in CI (but worked locally):
- name: "Echo the jenkins job template"
ansible.builtin.debug:
var: template_xml
verbosity: 1
Works locally and in CI:
- name: "Echo the jenkins job template"
debug:
var: template_xml
verbosity: 1
I believe - but have not confirmed - that the differences in local vs CI was ansible versions.
Local : 2.10
CI : 2.7
Explanation of the error :
No tasks to execute means it can not do the action that was described in your playbook
Root cause:
the installed version of Ansible doesn't support it
How to check :
ansible --version
Solution:
upgrade Ansible to a version which supports the feature you are trying to use
How to upgrade Ansible:
https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#selecting-an-ansible-version-to-install
Quick instruction for Ubuntu :
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
P.S: followed this path and upgraded from version 2.0.2 to 2.9
After upgrade, same playbook worked like a charm
For me the problem occurred with "systemd" module. Turned out that my ansible --version was 2.0.0.2 and module was first introduced in version 2.2. Updating my ansible to latest version fixed the problem.
playbook.yaml
- name: "Enable and start docker service and ensure it's not masked"
systemd:
name: docker
state: started
enabled: yes
masked: no
Error
ERROR! no action detected in task
etc..
etc..
etc..
- name: "Enable and start docker service and ensure it's not masked"
^ here
In my case this was fix:
ansible-galaxy collection install ansible.posix

Can I import a specific task from a role with dynamic name?

I have this role structure:
roles/
- a/
- tasks/
- main.yml
- k8s.yml
- templates/
- mytemplate.yml.j2
- b/
- tasks/
- main.yml
- k8s.yml
- templates/
- mytemplate.yml.j2
In my playbook I need to dynamically include a role, but running k8s.yml instead of main.yml. Something like this:
- roles:
- "{{ rolename }}/k8s.yml"
There's a include_role module that does exactly that:
- include_role:
name: "{{ rolename }}"
tasks_from: k8s
However this fails due to a bug that doesn't allow variables in the role name and will be fixed only on ansible 2.5 :(
Another approach would be to use include_tasks:
include_tasks: "roles/{{ rolename }}/tasks/k8s.yml"
The tasks are included and executed, but I get a failure message due to the fact that templates are not found (ansible tries to find the templates relative to the playbook dir, not the role dir):
TASK [Template processing] *********************************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: /home/myuser/myproject/mytemplate.yml.j2
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Could not find or access 'mytemplate.yml.j2'\nSearched in:\n\t/home/myuser/myproject/roles/a/tasks/templates/mytemplate.yml.j2\n\t/home/myuser/myproject/roles/a/tasks/mytemplate.yml.j2\n\t/home/myuser/myproject/templates/mytemplate.yml.j2\n\t/home/myuser/myproject/mytemplate.yml.j2"}
I even tried to overwrite the include_roles module with the patched version by adding it to myproject/library/, but I wasn't able to make it work.
Is there any way to accomplish this goal?
EDIT: The playbook works fine if the rolename variable is set on command line as an extra var, but it fails when it is set up with set_fact.
I was able to circumvent the bug by using hostvars:
- include_role:
name: "{{ hostvars[inventory_hostname]['rolename'] }}"
tasks_from: k8s
This way I can make it work until ansible 2.5 is released

Ansible stop playbook if file present

Is it possible to stop a playbook during his execution if a define file is present on my node and also output to explain why the playbook has stopped?
It is to prevent an accidental re-execution of my playbook on a node that has my application already installed because I generate a password during this install and I don't want to reinitialise this password.
You can use the fail module to force a failure with a custom failure message.
Couple this with a check for a file, using the stat module, and this should work easily enough for you.
A quick example or a one run playbook might look something like this:
- name: check for foo.conf
stat: path=/etc/foo.conf
register: foo
- name: fail if already run on host
fail: msg="This host has already had this playbook run against it"
when: foo.stat.exists
- name: create foo.conf
file: path=/etc/foo.conf state=touch

Resources