asible variable constructed of vars as a volume - ansible

Hello im working with ansible and in my docker container task im trying to set my volumes as a var.
Here is my volumes var
volumes_map: |
- "{{ airflow_script_location }}:{{ airflow_script_location_in_container }}:ro"
- "{{ airflow_data_input_location }}:{{ airflow_data_input_location_in_container }}:rw"
- "{{ airflow_data_output_success_location }}:{{ airflow_data_output_success_location_in_container }}:rw"
- "{{ airflow_data_output_failed_location }}:{{ airflow_data_output_failed_location_in_container }}:rw"
- "{{ airflow_root_location }}/requirements.txt:/requirements.txt"
- "{{ airflow_services_location }}/:{{ airflow_services_location_in_container }}:rw"
- "{{ airflow_root_location }}/airflow.cfg:{{ airflow_root_in_container }}/airflow.cfg"
- "{{ airflow_logs_location }}:{{ airflow_logs_location_in_container }}"
- "{{ airflow_conf_location}}:{{ airflow_conf_location_in_container }}"
and this is how im setting it in my volumes but this isnt working
volumes: "{{ volumes_map }}"
When i set the volumes directly without using the volumes_map it all works.

Try to Use template module
The "volumes_map" type is List,you can try
- debug: msg="{% for item in volumes_map %}{{item}}{% endfor %}"
Use Map it may help
- name: test
shell: echo "{{item}}"
with_items:
- "{{ airflow_script_location }}:{{ airflow_script_location_in_container }}:ro"
- "{{ airflow_root_location }}/airflow.cfg:{{ airflow_root_in_container }}/airflow.cfg"
- "{{ airflow_conf_location}}:{{ airflow_conf_location_in_container }}"
register: volumes_map
- debug: var=volumes_map.results|map(attribute='stdout')|list

Related

Can we have 2 with_items in ansible in a single task

Below is the condition
- name: Find the image
slurp:
src: "{{ IMAGE }}"
register: slurp_results
- name: Upload image
shell: |
skopeo copy -docker-archive:{{ item }}.tar docker://{{ URL }}/TESTIMAGE
with_items: "{{ (slurp_results.content|b64decode).splitlines() }}"
The above code works.
But I would need "TESTIMAGE" also to be replaced as {{ item }} like below.
skopeo copy -docker-archive:{{ item }}.tar docker://{{ URL }}/{{ item }}
How to define 2 with_items in a single shell task with 2 different slurp results
I believe you can by using the subelements module. Here is a link. Try going by this example:
- name: Setup MySQL users, given the mysql hosts and privs subkey lists
mysql_user:
name: "{{ item.0.name }}"
password: "{{ item.0.mysql.password }}"
host: "{{ item.1 }}"
priv: "{{ item.0.mysql.privs | join('/') }}"
with_subelements:
- "{{ users }}"
- mysql.hosts
Users is referred to as item.0 and hosts as item.1 and so on.

How to extract the output from stdout.lines in ansible

---
- name: Mikrotik info
hosts: mikrotik
connection: network_cli
remote_user: root
gather_facts: false
tasks:
- name: show info
routeros_command:
commands: /system routerboard print
register: rb_info
- name: Debug info
debug:
msg: "{{ rb_info.stdout_lines }}"
Output:
routerboard: yes
model: 751G-2HnD
serial-number: 3A6502B2A2E7
firmware-type: ar7240
factory-firmware: 3.0
current-firmware: 6.42.3
upgrade-firmware: 6.43.4
I need to filter it for "upgrade-firmware" string and get output like this:
upgrade-firmware: 6.43.4
I should use regex_replace? Or I can use grep or something like that?
Any thoughts are greatly appreciated.
Thank you
(update)
Use from_yaml and combine a dictionary. For example
- set_fact:
minfo: "{{ minfo|default({})|combine(item|from_yaml) }}"
loop: "{{ rb_info.stdout_lines }}"
- debug:
var: minfo['upgrade-firmware']
give
minfo['upgrade-firmware']: 6.43.4
(for the record)
Robust solution is to write the data to template and include_vars. The tasks below
- tempfile:
register: tempfile
- template:
src: minfo.j2
dest: "{{ tempfile.path }}"
- include_vars:
file: "{{ tempfile.path }}"
name: minfo
- debug:
var: minfo
with the template
shell> cat minfo.j2
{% for item in rb_info.stdout_lines %}
{{ item }}
{% endfor %}
should give
"minfo": {
"current-firmware": "6.42.3",
"factory-firmware": 3.0,
"firmware-type": "ar7240",
"model": "751G-2HnD",
"routerboard": true,
"serial-number": "3A6502B2A2E7",
"upgrade-firmware": "6.43.4"
}
The tasks below creates variable upgrade_firmware
- set_fact:
upgrade_firmware: "{{ item.split(':').1|trim }}"
loop: "{{ rb_info.stdout_lines|map('quote')|map('trim')|list }}"
when: item is search('^upgrade-firmware')
- debug:
var: upgrade_firmware
It is possible to put all the parameters into the dictionary
- set_fact:
minfo: "{{ minfo|default({})|
combine({item.split(':').0: item.split(':').1|trim}) }}"
loop: "{{ rb_info.stdout_lines|map('quote')|map('trim')|list }}"
- debug:
var: minfo['upgrade-firmware']

Loop through variables in task that has another list embedded in the variables

I am looking to loop through a list of variables. I have it looping through the of variables using with_items, however the catch is there is a list within that variables list that needs to have a different subset / number of variables that i need to iterate through as well.
I have tried different filters to include with_nested, with_subelements, and with_items. I know that they are moving towards loops as the primary driver moving forward so any solution ideally would leverage the ansible path moving forward. I am looking at having an "inner" loop or an external task that will iterate through the vlans_list and input that data as its to that point.
group Variables
vnic_templates:
- name: vNIC-A
fabric: A
mac_pool: testmac1
mtu: 1500
org_dn: org-root
redundancy_type: none
state: present
template_type: initial-template
vlans_list: ### THE PROBLEM CHILD
- name: vlan2
native: 'no'
state: present
- name: vlan3
native: 'no'
state: present
The actual task - i have issues when i have to input multiple vlans. The vnic template will have a 1 to one relationship however the vlans_list could be 1 vnic_template to many vlans.
ucs_vnic_template:
hostname: "{{ ucs_manager_hostname }}"
username: "{{ ucs_manager_username }}"
password: "{{ ucs_manager_password }}"
name: "{{ item.name }}"
fabric: "{{ item.fabric }}"
mac_pool: "{{ item.mac_pool }}"
mtu: "{{ item.mtu }}"
org_dn: "{{ item.org_dn }}"
redundancy_type: "{{ item.redundancy_type }}"
state: "{{ item.state }}"
template_type: "{{ item.template_type }}"
vlans_list:
- name: "{{ item.1.name }}"
native: "{{ item.1.native }}"
state: "{{ item.1.present }}"
# loop: "{{ vnic_templates | subelements('vlans_list') }}"
with_items:
- "{{ vnic_templates }}"
I am starting down the road of adding an include vlan_list.yml outside of this task but no familiar with out to do that.
Actual results are
The task includes an option with an undefined variable. The error was: 'item' is undefined\n\n
I need the create a single vnic template with multiple vlans defined in that list.
Another engineer i work with was able to solve the question. By the way the variables are laid out we were able to easily just change the code
Change this:
vlans_list:
- name: "{{ item.1.name }}"
native: "{{ item.1.native }}"
state: "{{ item.1.present }}"
To this:
vlans_list: "{{ item.vlans_list }}"
Full Code listed below.
- name: Add vNIC Templates
ucs_vnic_template:
hostname: "{{ ucs_manager_hostname }}"
username: "{{ ucs_manager_username }}"
password: "{{ ucs_manager_password }}"
name: "{{ item.name }}"
fabric: "{{ item.fabric }}"
mac_pool: "{{ item.mac_pool }}"
mtu: "{{ item.mtu }}"
org_dn: "{{ item.org_dn }}"
redundancy_type: "{{ item.redundancy_type }}"
state: "{{ item.state }}"
template_type: "{{ item.template_type }}"
vlans_list: "{{ item.vlans_list }}"
with_items:
- "{{ vnic_templates }}"

Looping in hostvars

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 }}"

Setting up correctly gateway_ip in Ansible function

I am using the following function to deploy an Openstack subnet using Ansible and variable file:
- name: Create the subnets
os_subnet:
cloud: "{{ item.cloud }}"
state: present
validate_certs: no
gateway_ip: "{{ item.gateway_ip | default(None) }}"
dns_nameservers: "{{ item.dns if item.dns is defined else omit }}"
enable_dhcp: yes
name: "{{ item.subnet }}"
network_name: "{{ item.network }}"
cidr: "{{ item.cidr }}"
allocation_pool_start: "{{ item.allocation_pool_start }}"
allocation_pool_end: "{{ item.allocation_pool_end }}"
host_routes: "{{ item.host_routes | default(omit) }}"
with_items:
- "{{ subnets }}"
tags: subnets
In my environment, I will have some subnets that will have gateway configured, some not. I would like to create a workaround to make it possible configuring gateway ip for some servers and for some of them not.
I have tried yet to configure it like this, but it will assign also for the ones that do not have the gateway_ip configured in the variable file a gateway. I have tried also the no_gateway_ip option, but for this one I didn't find the proper filter to get a gateway_ip when it is defined in the variable file.
Any way to trick this?
Found the way: no_gateway_ip should be involved, not gateway_ip.
- name: Create the subnets
os_subnet:
cloud: "{{ item.cloud }}"
state: present
validate_certs: no
no_gateway_ip: "{{ not (item.gateway_ip is defined) }}"
dns_nameservers: "{{ item.dns if item.dns is defined else omit }}"
enable_dhcp: yes
name: "{{ item.subnet }}"
network_name: "{{ item.network }}"
cidr: "{{ item.cidr }}"
allocation_pool_start: "{{ item.allocation_pool_start }}"
allocation_pool_end: "{{ item.allocation_pool_end }}"
host_routes: "{{ item.host_routes | default(omit) }}"
with_items:
- "{{ subnets }}"
tags: subnets

Resources