List in Ansible variable - ansible

I have Ansible Playbook which i want to use as Generic Playbook(choronically same for all).
Is there is any possible way to create List in inside vars: section and iterate it inside PlayBook? So that i just go and edit my vars section or var.yml file
PFB the part of my desired playbook
- name: Test playbook
hosts: all
remote_user: root
vars:
list_dict3:
- packages: [ 'python-setuptools','python-dev','libfuzzy-dev','libffi-dev','screen']
tasks:
- name: Accessing list of dictionary
apt: pkg={{item.packages}} state=present
with_items: list_dict3

Not sure what you really want, because your variable structure is very strange, but to make your apt task correct, you should write:
- name: Accessing list of dictionary
apt:
name: "{{ item }}"
state: present
with_items: "{{ list_dict3[0].packages }}"

Related

ansible loop with include_variable

I have a playbook, there are multiple yaml files under include_vars section of the task as you see i am defining them individually one by one. I'm wondering if i can pass them through the loop.
I went through the google and ansible doc link here but i don't find loop example however, i see with_first_found but i don't want that.
My playbook below
---
- name: Creating aws host
hosts: localhost
connection: local
become: yes
tasks:
- include_vars: awsvariable.yml
no_log: true
- include_vars: vaults/mysecrets.yml
no_log: true
- include_vars: vaults/mydev.yml
no_log: true
- include_vars: requirements.yml
Below is what i am considering
Is this doable as below?
tasks:
- include_vars: "{{ item }}"
loop:
- awsvariable.yml
- vaults/mysecrets.yml
- vaults/mydev.yml
- requirements.yml
OR
tasks:
- include_vars: ['awsvariable.yml', 'vaults/mysecrets.yml', 'vaults/mydev.yml', 'requirements.yml']
no_log: true
Please suggest, if we can better align them some other way around.
ansible version: 2.9
BR.
I see you are already close to your answer and yes loop should work, try to run your play in the dry run mode and set the no_log: false to see if your variables are getting expanded.
Example:
$ ansible-playbook test_play.yml --check --ask-vault-pass
your code
- include_vars: "{{ item }}"
loop:
- 'awsvariable.yml'
- 'vaults/mysecrets.yml'
- 'vaults/mydev.yml'
- 'requirements.yml'
no_log: true
Use dir to include all the files in a folder.
- name: Include variable files
include_vars:
dir: vars
extensions:
- "yml"
Alternatively can use both loop or with_items to loop through the filenames and include them.
- name: Include variable files
include_vars: "{{ item }}"
with_items:
- "vars/file.yml"
- "vars/anotherfile.yml"
Or using the newer loop.
- name: Include variable files
include_vars: "{{ item }}"
loop:
- "vars/file.yml"
- "vars/anotherfile.yml"
Seems the include_vars module can't work with loops. You could use the include_task module to loop over a file that has a single task to include_vars:
---
- hosts: localhost
gather_facts: false
vars:
files_to_load:
- file1.yml
- file2.yml
- file3.yml
tasks:
- include_tasks: include_vars.yml
loop: "{{ files_to_load }}"
loop_control:
loop_var: file_to_load
ant the include_vars.yml file:
- name: include vars {{ file_to_load }}
include_vars: "{{ file_to_load }}"
UPDATE:
Regarding loop syntax that i tried and didnt work, the below attempts failed:
1st:
- include_vars: "{{ item }}"
loop: - "{{ files_to_load }}"
2nd:
- include_vars: "{{ item }}"
loop:
- "{{ files_to_load }}"
i am aware that this syntax works:
- name: Include variable files
include_vars: "{{ item }}"
loop:
- "vars/file.yml"
- "vars/anotherfile.yml"
but personally i dont find convenient the fact that you need to list the loop items on task level.

Where to put (-) hyphen in yaml ansible play books?

I am very confused, in the play book where actually we put single hyphen (-). I found similar threads here, but still confused, so decided to draft one new. I have read it will be used to indicate start of a list item. again i have difficulty in understanding where is the start of list and where is start of dictionary.
Can some experts explain me where should i put hyphen in below code. and why is that?
---
connection: local
gather_facts: false
hosts: rtr
tasks:
name: "read configs"
read_csv:
path: "{{ aws_config }}"
register: aws_requests
run_once: true
debug:
msg: "{{ aws_requests.list }}"
name: "display awsconfigs requests"
run_once: true
name: "set awsconfigs requests"
run_once: true
set_fact:
aws_configs: "{{ aws_requests.list }}"
name: "build template"
template:
dest: "{{ config_filename }}"
lstrip_blocks: true
src: "{{ template }}"
I recommend that you read the "Intro to playbooks", which should answer your questions, but below is a summary.
As you noted correctly, hyphens are list items in YAML. YAML documents start with ---, which is why there are hyphens at the start of the file.
The starting point for any Ansible playbook is the playbook itself in the file. The playbook file itself may contain one or more so-called "plays", each as its own list element. Each play typically contains a hosts and a tasks part. In many playbooks, there is just one "play", so your typical minimal playbook looks like this:
---
- hosts: webservers
tasks:
- name: Task 1
...
As you can see above, each "play" then has a list of tasks, each starting with a hyphen. So in the following example there are two tasks, each with a name and the module (yum and service in this case):
---
- hosts: webservers
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: ensure apache is running
service:
name: httpd
state: started
Each Ansible module has different arguments, so you'll need to check the modules documentation for each one how to specify these arguments.
So the correct version for your playbook above would look like this:
---
- connection: local
gather_facts: false
hosts: rtr
tasks:
- name: "read configs"
read_csv:
path: "{{ aws_config }}"
register: aws_requests
run_once: true
- name: "display awsconfigs requests"
debug:
msg: "{{ aws_requests.list }}"
run_once: true
- name: "set awsconfigs requests"
run_once: true
set_fact:
aws_configs: "{{ aws_requests.list }}"
- name: "build template"
template:
dest: "{{ config_filename }}"
lstrip_blocks: true
src: "{{ template }}"

Can ansible variables be used to declare hosts in a playbook?

I have a playbook in the format below:
---
- hosts: myIP
tasks:
- name: Install a yum package in Ansible example
yum:
name: ThePackageIWantToInstall
state: present
where myIP and ThePackageIWantToInstall are variables.
When the job template runs, I would like the user in the extra variables popup to be able to go with:
myIP = 192.168.1.1
ThePackageIWantToInstall = nano
As the documentation doesn't provide an example of supplying a variable via a job template, is this possible?
Yes.
- name: Do The Thing
hosts: "{{ foo }}"
roles:
- "{{ role }}"
Need mustaches and quotes.
to run from popup
(I don't use this, but it was suggested as an edit, thanks...)
foo: value
I have achieved similar thing with add_hosts. Here iam not installing package but creating file with name passed from command line. Any number of hosts (separated by commas can be passed from command line).
# cat addhost2.yml
- hosts: localhost
gather_facts: no
tasks:
- add_host:
name: "{{ item }}"
groups: hosts_from_commandline
with_items: "{{ new_hosts_passed.split(',') }}"
- hosts: hosts_from_commandline
tasks:
- name: Ansible create file with name passed from commandline
file:
path: "/tmp/{{ filename_from_commandline }}"
state: touch
# ansible-playbook -i hosts addhost2.yml --extra-vars='new_hosts_passed=192.168.3.104,192.168.3.113 filename_from_commandline=lathamdkv'
Hope this helps

How can I pass Ansible playbook variables from a master playbook to a linked playbook?

I'm trying to find out how I can pass Ansible playbook variables defined in a 'master' playbook into other playbooks that I've already referenced in my master playbook.
For example, with the below 'master' playbook, I'd like to pass the values of sethostname and setipaddress to playbook[1-3].yml referenced in my tasks section. This would be akin to calling functions in other programming languages.
---
- hosts: all
become: yes
vars_prompt:
- name: "sethostname"
prompt: "What will be the machine's hostname?"
private: no
- name: "setipaddress"
prompt: "What will be the machine's IP address?"
private: no
tasks:
- include: playbook1.yml
- include: playbook2.yml
- include: playbook3.yml
As of Ansible 2.4 you can now import playbooks, meaning they will get pre-processed at the time the playbook is parsed, and will run in the order you import them. Check out the docs for the full info on import vs. include here http://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_includes.html
You can pass vars to them just like you can to other include_* tasks.
tasks:
- import_playbook: playbook1.yml
vars:
sethostname: "{{ sethostname }}"
setipaddress "{{ setipaddress }}"
Kellie's answer is not exactly accurate , playbooks may not be imported at task level only at the topmost level of a playbook. So this works:
- import_playbook: playbook1.yml
vars:
sethostname: "{{ sethostname }}"
setipaddress "{{ setipaddress }}"

Ansible - multiple roles

I am trying to run multiple roles using with_items command, however I am getting error:
"ERROR! 'item' is undefined"
role.yml:
---
- hosts: '{{ host }}'
become: yes
roles:
- role: "{{item}}"
with_items: "{{ roles }}"
Here is my command:
ansible-playbook -i ./inventory/Dev ./playbooks/role.yml --extra-vars='{"host": "db", "roles": ["mysql", "apache"]}'
You cannot do it this way. with_ loops are not valid for roles.
If anything, you need to provide a list of roles to the roles: directive, so the syntax would be just like for the list of host groups hosts: '{{ host }}'. The problem is: Ansible does not resolve the variable for roles, so roles: '{{ roles }}' does not work.
What you can do, however, is to use include_role module in which you can access the variables.
No, include_role module doesn't take {{ item }} from the with_items as a value for name either.
So the only workaround I can think of (assuming you don't want to process the JSON beforehand) is to the include the roles statically:
tasks:
- include_role:
name: "mysql"
when: "'mysql' in roles"
- include_role:
name: "apache"
when: "'apache' in roles"
The roles need to exist on the control machine anyway, so all their names are predefined.
You cannot use with_ loop with roles directive.
A simple solution would be to use normal yaml list like below:
---
- hosts: '{{ host }}'
become: yes
roles:
- myrole1
- myrole2
Another example where you could declare the roles as well as pass corresponding variables to the role would be like below:
---
- hosts: '{{ host }}'
become: yes
roles:
- role:
name: myrole1
vars:
host: "db1"
myroles:
- mysql1
- apache1
- role:
name: myrole2
vars:
host: "db2"
myroles:
- mysql2
- apache2
Also avoid using ansible keywords as your variable names
Finally your command to run your playbook will be as below:
ansible-playbook -i ./inventory/Dev ./playbooks/role.yml

Resources