I have an Ansible Playbook myPlayBook.yml. It has two plays and each plays has one or more tasks.
I use the command as follows to run my playbook:
ansible-playbook myPlayBook.yml
So every thing is OK and my tasks are executed successfully. Now, after the first running I want to run my playbook again from the first play (similar to the first running but automatically). Is there a way to do that?
(I saw that it can be done for a specific task or play with include or include_tasks, but what about for a playbook?)
Now, after the first running I want to run my playbook again from the
first play (similar to the first running but automatically).
You can form your tasks as role and execute it via include_role from playbook multiple times:
- name: 'Include role'
include_role:
name: '{{ app_role}}'
- debug:
msg: "{{ inventory_hostname }}"
Create role by the following path roles/inventory_role that consist of one task. From playbook you can execute role just call it multiple times:
- name: 'Include role inventory_role'
include_role:
name: 'inventory_role'
- name: 'Include role inventory_role'
include_role:
name: 'inventory_role'
Or you can use something like this:
- { role: 'inventory_role' }
- { role: 'inventory_role' }
NOTE:
Ansible will only allow a role to execute once, even if defined
multiple times, if the parameters defined on the role are not
different for each definition.
See for more details: Role Duplication and Execution.
Execute an Ansible Playbook periodically
Ansible Tower have job with scheduled launch type.
Related
My use case is to use a single playbook to run the same role on 2 different host groups, but I want to pass different variable values depending on the host group the role is executing against.
I've tried many ways of doing this, but I am finding the second play for the second host group is not executed.
---
- name: Run against webservers
hosts: webservers
vars: var1: "val_a"
roles:
- common_role
- name: Run against dbservers
hosts: dbservers
vars: var1: "val_b"
roles:
- common_role
```
when I execute code similar to above, it only executes the first play, against webservers, and terminates. Is my use case valid? (i.e. execution of same role, against 2 host groups, but passing different variable values for each group, within single playbook)
You can set the ignore_errors on the failing task to continue the execution.
- fail:
when: var1 == 'val_a'
ignore_errors: true
But keep in mind that current role continue to execute rest of the tasks after failing one too.
I have a playbook with this structure:
---
- hosts: foo-servers
roles:
- foo_setup
become: yes
tags: tweaks
- hosts: bar-servers
roles:
- bar_setup
become: yes
tags: tweaks
[a few more server groups with a similar pattern]
I have a somewhat similar feature to deploy in all servers but each server group has it's own small differences, so I need to keep separate roles for each group.
I also want to run just a select group of tasks from each role, the ones tagged 'tweaks', in all hosts.
And all hosts should be run with raised privileges, but that is not true for all playbooks, so I want that setting to apply just to this playbook (no global vars).
I would like to move all the repeated parameters - become: yes and tags: tweaks outside of host: plays where they will be indicated to apply to all roles bellow. Something to the effect of
--
- all_hosts_this_playbook:
become: yes
tags: tweaks
- hosts: foo-servers
roles:
- foo_setup
- hosts: bar-servers
roles:
- bar_setup
I suppose this is possible in the command line. Like ansible-playbook setup_tweaks.yml --tags "tweak" --become? But is there a playbook equivalent? I'd rather have these in the file than in the command line, where I often forget to add stuff.
And looping doesn't work...
ERROR! 'loop' is not a valid attribute for a Play
- name: Make tweaks in many servers
become: yes
tags: tweaks
hosts: "{{ item.host }}"
roles:
- "{{ item.role }}"
loop:
- { host: 'foo-servers', role: 'foo_setup' }
- { host: 'bar-servers', role: 'bar_setup' }
I also want to add post_tasks: to be run in all servers (maybe they also need to be tagged?):
post_tasks_all_hosts:
- name: Upgrade system
apt:
autoremove: yes
autoclean: yes
update_cache: yes
upgrade: dist
tags: tweaks
- name: Reboot
shell: sleep 2 && reboot
async: 3
poll: 0
tags: tweaks
Is it possible to define playbook-wide pre_tasks or post_tasks?
Here Ansible: How to declare global variable within playbook? it is indicated that one 'cannot define a variable accessible on a playbook level', but in my case it's not variables - it's task parameters and post_tasks:.
Maybe the parameters and the 'pre/post tasks' are different problems with different solutions, but I decided to ask in the same place because they both fall on the same category of parameters that I'd like to set for the whole playbook, outside of host: plays.
Q: "I suppose this is possible in the command line. Like ansible-playbook setup_tweaks.yml --tags "tweak" --become? But is there a playbook equivalent?"
A: No. There is no such playbook equivalent.
Isn't this is a misunderstanding of the command-line option --tags
only run plays and tasks tagged with these values
versus
tag inheritance ?
Adding tags: to a play, or to statically imported tasks and roles, adds those tags to all of the contained tasks...When you apply tags: attributes to structures other than tasks, Ansible processes the tag attribute to apply ONLY to the tasks they contain. Applying tags anywhere other than tasks is just a convenience so you don’t have to tag tasks individually.
Details
In the play below tag "tweaks" is added to all of the contained tasks
- hosts: foo-servers
roles:
- foo_setup
tags: tweaks
The command below selects only tasks tagged "tweaks"
ansible-playbook setup_tweaks.yml --tags "tweak"
Q: "Is it possible to define playbook-wide pre_tasks or post_tasks?"
A: No. It's not possible. The scope of pre/post_tasks is the play.
I have set of tasks that i want to execute at set of hosts sequentially.
Example is below.
hosts: all
tasks:
- name: do some work
include_tasks: tasks_here.yml
loop: "{{ vars[play_hosts] }}"
ansible-playbook main.yml --limit myhosts
I expect that set of tasks would be executed at first host, then at second host etc... But in fact these tasks are being executed simulatineously at all hosts in "limit".
I suspect that it's happening because I use limit but i need it in my case.
So what I should I do?
By default, as specified here:
plays run with a linear strategy, in which all hosts will run each task before any host starts the next task.
You can use the strategy serial: 1 to execute the tasks on each host sequentially.
For example:
- hosts: all
serial: 1
tasks:
...
Trying to use vars_prompt on main.yml task inside role but I get error:
tasks/main.yml file for role 'roleName' must contain a list of tasks
vars_prompt:
- name: 'variableName'
prompt: "Prompting User "
private: no
default: ''
- name: taskName
uri:
url: "{{ variableName }}"
register: response
ignore_errors: yes
- debug:
var: response
If I move the prompting to playbook main.yml it works but I need to be able to do it within the task.
Thoughts?
vars_prompt can only be defined on a play. A task list is so named because it can only consist of tasks; metadata like vars, vars_prompt, hosts, etc. can only be set at the play level.
Consider avoiding the use of vars_prompt if at all possible. If you need input from the user, have them provide it on the command line using -e variable=value or in a file and using -e #somefile.yml.
We have a "periodic" tag in our roles that is intended to be run at regular intervals by our Ansible box for file assurance, etc. Would it be possible to have a playbook for periodic runs that calls the other playbooks with the appropriate host groups and tags?
The only way to execute an Ansible playbook "with the appropriate host groups and tags" is to run ansible-playbook executable. This is the only case in which all the data structures starting from the inventory would be created in isolation from the currently running playbook.
You can simply call the executable using command module on the control machine:
- hosts: localhost
tasks:
- command: ansible-playbook {{ playbook }} --tags {{ tags }}
You can also use local_action or delegate_to.
It might be that you want to include plays, or use roles, however given the problem description in the question, it's impossible to tell.
Here is what we ended up with: It turns out that tags and variables passed on the command-line are inherited all the way down the line. This allowed us to pass this on the command line:
ansible-playbook -t periodic periodic.yml
Which calls a playbook like this:
---
- name: This playbook must be called with the "periodic" tag.
hosts: 127.0.0.1
any_errors_fatal: True
tasks:
- fail:
when: periodic not True
- name: Begin periodic runs for type 1 servers
include: type1-server.yml
vars:
servers:
- host_group1
- host_group2
- ...
- name: Begin periodic runs for type 2 servers
...
Our 'real' playbooks have - hosts: "{{ servers }}" so that they can be inherited from the parent. The tasks in our roles are tagged with "periodic" for things that need to be run on a schedule. We then use SystemD to schedule the runs. You can use cron, but SystemD is better IMHO. Examples can be provided upon request.