This may be an elementary question. I am using the following Ansible modules and was wanting to streamline my playbooks by reducing duplicate lines/variables.
https://github.com/HewlettPackard/hpe3par_ansible_module
I see that each task references a module that is using the same connection parameters. The variables are already defined in a parameters file but is there a way to move parameters to be more global so it doesn't have to be repeated in each task.
My playbook:
---
- name: Create 3PAR host and volume
hosts: localhost
tasks:
- name: Load Storage System Vars
include_vars: 'properties/storage_system_properties.yml'
- name: Load Host Vars
include_vars: 'properties/host_properties.yml'
- name: Create Host "{{ host_name }}"
hpe3par_host:
storage_system_ip="{{ storage_system_ip }}"
storage_system_username="{{ storage_system_username }}"
storage_system_password="{{ storage_system_password }}"
state=present
host_name="{{ host_name }}"
host_persona="{{ host_persona }}"
host_domain="{{ host_domain }}"
host_iscsi_names="{{ host_iscsi_names }}"
- name: Create Volume "{{ volume_name }}"
hpe3par_volume:
storage_system_ip="{{ storage_system_ip }}"
storage_system_username="{{ storage_system_username }}"
storage_system_password="{{ storage_system_password }}"
state=present
volume_name="{{ volume_name }}"
cpg="{{ cpg }}"
size="{{ size }}"
- name: Create VLUN
hpe3par_vlun:
storage_system_ip="{{ storage_system_ip }}"
storage_system_username="{{ storage_system_username }}"
storage_system_password="{{ storage_system_password }}"
state=export_volume_to_host
volume_name="{{ volume_name }}"
host_name="{{ host_name }}"
Desired playbook.
---
- name: Create 3PAR host and volume
hosts: localhost
vars_file:
- properties/storage_system_properties.yml
tasks:
- name: Load Host Vars
include_vars: 'properties/host_properties.yml'
- name: Create Host "{{ host_name }}"
hpe3par_host:
state=present
host_name="{{ host_name }}"
host_persona="{{ host_persona }}"
host_domain="{{ host_domain }}"
host_iscsi_names="{{ host_iscsi_names }}"
- name: Create Volume "{{ volume_name }}"
hpe3par_volume:
state=present
volume_name="{{ volume_name }}"
cpg="{{ cpg }}"
size="{{ size }}"
- name: Create VLUN
hpe3par_vlun:
state=export_volume_to_host
volume_name="{{ volume_name }}"
host_name="{{ host_name }}"
properties/storage_system_properties.yml
storage_system_ip: "192.168.1.10"
storage_system_username: "3paruser"
storage_system_password: "3parpass"
An option would be to use include_tasks. See example below.
> cat tasks-001.yml
- debug: msg="{{ var_001 }}-{{ var_002 }}-{{ var_003 }}"
> cat test-19.yml
- hosts: localhost
gather_facts: no
vars:
var_001: "001"
var_002: "002"
var_003: "003"
tasks:
- include_tasks: tasks-001.yml
- include_tasks: tasks-001.yml
vars:
var_003: "444"
- include_tasks: tasks-001.yml
vars:
var_003: "555"
- include_tasks: tasks-001.yml
vars:
var_001: "111"
var_002: "222"
- include_tasks: tasks-001.yml
vars:
var_001: "111"
var_002: "222"
var_003: "333"
- include_tasks: tasks-001.yml
> ansible-playbook test-19.yml | grep msg
"msg": "001-002-003"
"msg": "001-002-444"
"msg": "001-002-555"
"msg": "111-222-003"
"msg": "111-222-333"
"msg": "001-002-003"
Related
I have a bunch of root servers with different IP addresses. I'm trying to configure the ufw firewall on the server with MySQL server to only allow access from my servers (might change to webservers later) with Ansible. Initially, I only had the FQDNs in the inventory but added the ansible_host IPs because the firewall is not going to resolve the host names (makes sense).
Unfortunately I do not know how to access the ansible_host in the loop query("inventory_hostnames", "all")
My inventory:
all:
vars:
ansible_ssh_user: me
children:
sqlserver:
hosts:
sqlserver.my-domain.de:
ansible_ssh_user: mysql_me_user
ansible_host: 1.1.1.1
webserver:
hosts:
webserver1.my-domain.de:
ansible_host: 2.2.2.2
webserver2.my-domain.de:
ansible_host: 3.3.3.3
now I am trying to loop in the playbook:
- hosts: '{{target|default("sqlserver")}}'
roles:
- { name: oefenweb.ufw, become: yes } # needs root but does not define become by itself...
vars:
ufw_logging: true
ufw_rules:
- rule: allow
to_port: 22
protocol: tcp
tasks:
- name: open MySQL for servers in my
ufw:
rule: allow
to_port: 3306
protocol: tcp
from_ip: '{{ item }}'
loop: '{{ hosts|default(query("inventory_hostnames", "all")) }}'
tags: test
become: true
There are many options. Make your choice depending on the use case.
For example, the play below
shell> cat pb.yml
- hosts: '{{ target|default("sqlserver") }}'
tasks:
- debug:
msg: "{{ item }}: {{ ansible_host }}"
loop: "{{ clients|default(groups.webserver) }}"
vars:
ansible_host: "{{ hostvars[item].ansible_host }}"
gives
shell> ansible-playbook pb.yml
PLAY [sqlserver] *****************************************************************************
TASK [debug] *********************************************************************************
ok: [sqlserver.my-domain.de] => (item=webserver1.my-domain.de) =>
msg: 'webserver1.my-domain.de: 2.2.2.2'
ok: [sqlserver.my-domain.de] => (item=webserver2.my-domain.de) =>
msg: 'webserver2.my-domain.de: 3.3.3.3'
PLAY RECAP ***********************************************************************************
sqlserver.my-domain.de: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Example of the project for testing
shell> tree .
.
├── ansible.cfg
├── hosts
└── pb.yml
0 directories, 3 files
shell> cat ansible.cfg
[defaults]
gathering = explicit
inventory = $PWD/hosts
stdout_callback = yaml
shell> cat hosts
all:
vars:
ansible_ssh_user: me
children:
sqlserver:
hosts:
sqlserver.my-domain.de:
ansible_ssh_user: mysql_me_user
ansible_host: 1.1.1.1
webserver:
hosts:
webserver1.my-domain.de:
ansible_host: 2.2.2.2
webserver2.my-domain.de:
ansible_host: 3.3.3.3
shell> cat pb.yml
- hosts: '{{ target|default("sqlserver") }}'
tasks:
- debug:
msg: "{{ item }}: {{ ansible_host }}"
loop: "{{ clients|default(groups.webserver) }}"
vars:
ansible_host: "{{ hostvars[item].ansible_host }}"
Create the list and the dictionary below
clients: "{{ groups.webserver }}"
ah_list: "{{ clients|map('extract', hostvars, 'ansible_host')|list }}"
ah_dict: "{{ dict(clients|zip(ah_list)) }}"
give
ah_list:
- 2.2.2.2
- 3.3.3.3
ah_dict:
webserver1.my-domain.de: 2.2.2.2
webserver2.my-domain.de: 3.3.3.3
Then, all tasks below give the same results
2a)
- debug:
msg: "{{ item.key }}: {{ item.value }}"
with_dict: "{{ ah_dict }}"
2b)
- debug:
msg: "{{ item.0 }}: {{ item.1 }}"
with_together:
- "{{ clients }}"
- "{{ ah_list }}"
2c)
- debug:
msg: "{{ item }}: {{ ah_dict[item] }}"
loop: "{{ clients }}"
Example of a complete playbook for testing
- hosts: '{{ target|default("sqlserver") }}'
vars:
clients: "{{ groups.webserver }}"
ah_list: "{{ clients|map('extract', hostvars, 'ansible_host')|list }}"
ah_dict: "{{ dict(clients|zip(ah_list)) }}"
tasks:
- debug:
var: ah_list
- debug:
var: ah_dict
- debug:
msg: "{{ item.key }}: {{ item.value }}"
with_dict: "{{ ah_dict }}"
- debug:
msg: "{{ item.0 }}: {{ item.1 }}"
with_together:
- "{{ clients }}"
- "{{ ah_list }}"
- debug:
msg: "{{ item }}: {{ ah_dict[item] }}"
loop: "{{ clients }}"
As I was writting the question I understood that should google for accessing inventory property and found a solution in Accessing inventory host variable in Ansible playbook - use
from_ip: '{{ hostvars[item].ansible_host }}'
for my task.
I hope that this the way to go.
I have this playbook below to set user/group on the user's home directory.
jimbo and bobo here have different UID and GIDs on the different boxes.
Running this script will set the UID/GID ownership of the directories incorrectly.
For example, it will set /home/jimbo on operatorbox1 (1) to be owned by the UID of jimbo from operatorbox2 (2) - which is of course not the correct UID on operatorbox1 (1).
It does this seemingly randomly. If I run this playbook multiple times the ownership of the directories will flip back and forth.
Guessing I have something fundamental missing here. Why is this happening? Thanks!
ansible-playbook v2.9.23
./vars/operators.yml
---
operators:
jimbo: sshekeywhatever
bobo: sshkeywhatever
playbook.yml
---
- name: Setup operators
hosts:
- bastionbox
- operatorbox
become: true
vars_files:
- "./vars/operators.yml"
tasks:
- name: Set home directory permissions
file:
path: "/home/{{ item.key }}"
state: directory
owner: "{{ item.key }}"
group: "{{ item.key }}"
recurse: true
with_dict:
- "{{ operators }}"
I can't reproduce the problem. Below is a playbook for testing
- hosts: bastionbox,operatorbox
gather_facts: false
become: true
vars:
operators: [jimbo, bobo]
tasks:
- name: Create users
user:
name: "{{ item }}"
shell: /usr/sbin/nologin
uid: "{{ range(2500, 2600)|random }}"
loop: "{{ operators }}"
when: create_users|d(false)|bool
- name: List users uid
block:
- getent:
database: passwd
- debug:
msg: "{{ inventory_hostname }} {{ item }} uid: {{ getent_passwd[item].1 }}"
loop: "{{ operators }}"
when: list_users|d(false)|bool
- name: Set home directory owner and group
file:
state: directory
path: "/home/{{ item }}"
owner: "{{ item }}"
group: "{{ item }}"
recurse: true
loop: "{{ operators }}"
when: set_homes|d(false)|bool
- name: List homes
block:
- find:
paths: /home
file_type: directory
patterns: "{{ operators }}"
register: out
- debug:
msg: "{{ inventory_hostname }} {{ item.path }} uid: {{ item.uid }}"
loop: "{{ out.files }}"
loop_control:
label: "{{ inventory_hostname }}"
when: list_homes|d(false)|bool
- name: Delete users
user:
name: "{{ item }}"
state: absent
remove: true
loop: "{{ operators }}"
when: delete_users|d(false)|bool
Create users
shell> ansible-playbook -e create_users=true pb.yml
List users
shell> ansible-playbook -e list_users=true pb.yml
msg: 'bastionbox jimbo uid: 2572'
msg: 'operatorbox jimbo uid: 2537'
msg: 'bastionbox bobo uid: 2505'
msg: 'operatorbox bobo uid: 2557'
List homes
shell> ansible-playbook -e list_homes=true pb.yml
msg: 'bastionbox /home/bobo uid: 2505'
msg: 'operatorbox /home/jimbo uid: 2537'
msg: 'bastionbox /home/jimbo uid: 2572'
msg: 'operatorbox /home/bobo uid: 2557'
Set homes (task is idempotent)
shell> ansible-playbook -e set_homes=true pb.yml
TASK [Set home directory owner and group] *************************
ok: [operatorbox] => (item=jimbo)
ok: [bastionbox] => (item=jimbo)
ok: [operatorbox] => (item=bobo)
ok: [bastionbox] => (item=bobo)
I am trying to get the pertinent fields from a vmware module output, I am filtering with json, but the says my variable target_vm_name is undefined. how do I get a variable with only the matching criteria which is filtered by the ip address of the list of hosts I want to iterate through?
code is below:
- name: Loop thru hosts and get IPs
hosts: rpa_test
vars:
ip_addr:
"{{ lookup('dig', ansible_host) }}"
tasks:
- debug:
msg: "System {{ inventory_hostname }} has ip address of {{ ip_addr }}"
- name: get vm info based on ip
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vault_vcenter_admin_name }}"
password: "{{ vault_vcenter_admin_password }}"
validate_certs: False
delegate_to: localhost
register: vm_info
vars:
target_vm_name: "{{ vm_info.virtual_machines | json_query(query) }}"
query: "[?ip_address=={{ ip_addr }}]"
- debug:
msg: "{{ target_vm_name.virtual_machines.guest_name }}"
vars is not at the right place inside the community.vmware.vmware_vm_info task ,
you should put it in the debug task:
tasks:
- debug:
msg: "System {{ inventory_hostname }} has ip address of {{ ip_addr }}"
- name: get vm info based on ip
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vault_vcenter_admin_name }}"
password: "{{ vault_vcenter_admin_password }}"
validate_certs: False
delegate_to: localhost
register: vm_info
- debug:
msg: "{{ target_vm_name.virtual_machines.guest_name }}"
vars:
target_vm_name: "{{ vm_info.virtual_machines | json_query(query) }}"
query: "[?ip_address=={{ ip_addr }}]"
I am executing below as ansible playbook in loop with_together but need to know the status of the each task which is defined switch-host-config.yaml, but when i print register variable "sw_output" its not showing the task result it shows the with_together defined list...
is there any method or way to identify the task status in defined switch-host-config.yaml playbook.
- hosts: "{{ data_sw_ip1 }}"
connection: local
gather_facts: False
tasks:
- name: sw-host task
include_tasks: switch-host-config.yaml
vars:
- nic1_swport: "{{ item.0 }}"
- nic2_swport: "{{ item.1 }}"
- id_host: "{{ item.2}}"
register: sw_output
with_together:
- "{{ nic1_swport1 }}"
- "{{ nic2_swport }}"
- "{{ id_host }}"
ignore_errors: yes
- debug:
msg: "{{ sw_output }}"
I'm wondering if it is possible to perform a loop in the hostvars folder when using Ansible?
Here is what I've tried but haven't had success in making it work - or is it just not possible to do?
---
list_pool: 'list ltm pool {{ items }}'
with_items:
- 'abc123'
- 'def456'
I would use the "list_pool" variable in a playbook afterward:
- name: List pool
bigip_command:
server: "{{ some_server }}"
user: "{{ some_user }}"
password: "{{ some_password }}"
commands:
- "{{ list_pool }}"
validate_certs: no
delegate_to: localhost
Not sure what you mean when you say you want to loop over hostvars folder.
From what I can interpret from your tasks is: "You need to execute big-ip command list ltm <pool-name> for multiple pools in the list list_pool"
If that's what you're after, this should work:
- name: Set list_pool fact
set_fact:
list_pool: "{{ list_pool | default([]) + [item] }}"
with_items:
- 'abc123'
- 'def456'
- name: List pool
bigip_command:
server: "{{ some_server }}"
user: "{{ some_user }}"
password: "{{ some_password }}"
commands:
- "list ltm {{ item }}"
validate_certs: no
delegate_to: localhost
with_items: "{{ list_pool }}"
I got this working with the following solution:
hostvars file would look like this:
---
pre_checks:
checks:
pool:
- name: "pool_123"
- name: "pool_456"
...
And the play would look like this:
--output truncated---
- name: Fetch device host_vars
set_fact:
device_config: "{{ ((lookup('file','{{playbook_dir}}/host_vars/{{inventory_hostname}}.yml')) | from_yaml) }}"
- name: Check pool
bigip_command:
server: "{{ inventory_hostname }}"
user: "{{ remote_username }}"
password: "{{ remote_passwd }}"
commands:
- "list ltm pool {{ item }}"
validate_certs: no
with_items:
- "{{ device_config.pre_checks | json_query('checks.pool[*].name') }}"
delegate_to: localhost
when: "'active' in Active_LTM['stdout'][0]"
register: Pre_Checks
- name: Verify pool
debug: var=item
with_items: "{{ Pre_Checks.results | map(attribute='stdout_lines') | list }}"