I'm struggling with syntax to build and add to list dynamically. Would like to do it in an ansible line without going to a jinja2 template. I've been messing around while but the below is where I started. The error is in the line to set the fact.
- name: Assign data to the correct list based on the meta value.
set_fact:
"{{ next_reference.list_name }}": "{{ next_reference.list_name|default([]) + [ input_data ] }}"
loop: "{{ reference_list }}"
loop_control:
loop_var: next_reference
when: input_data.meta == next_reference.meta
reference_list:
- meta: "test1"
list_name: "test1_list"
- meta: "test2"
list_name: "test2_list"
- meta: "test3"
list_name: "test3_list"
input_data_list:
- meta: "anp"
value1: "one"
value2: "two"
Thanks for any assistance may have to go the jinja2 route in the meantime.
Without Jinja, it's not possible to indirectly declare or modify variables in Ansible. Instead, an appropriate data structure might serve the purpose, e.g.
t:
t1: "{{ test1_list|default([]) }} + {{ input_data }}"
t2: "{{ test2_list|default([]) }} + {{ input_data }}"
t3: "{{ test3_list|default([]) }} + {{ input_data }}"
Thanks for the reply. This issue was a reminder that jinja2 and ansible are simple tools not programming languages so the key is to think simplistically.
If you want to change data in a list of dictionaries. The best way to do it is trawl through the current list and pull out the data from the dictionary you want to create a new dictionary put the new data in it or amend it. Stick this new dictionary in a list.
Use rejectattr to remove the dictionary from the current list. Use a simple jinja2 template to recombine the new and old list.
Related
I need to extract some text from a variable in ansible.
- name: Find modules
shell: find "{{ role_path }}/files/{{ flavor_modules }}/modules.d/" -name "*.yml"
register: modules_list
- debug:
msg: "aca {{ item }}"
with_items: "{{ modules_list }}"
So modules list returns something like this: /etc/ansible/roles/filebeat/files/something/modules.d/haproxy.yml
I need to register or create a new variable that looks like this: haproxy.yml
I been trying with some regex expressions with no luck.
I'm currently writing a small Ansible playbook whose job is to put in an additional domain in the search list in /etc/resolv.conf.
The second domain to add to the search list must contain part of the hostname of the target hosts. I'm getting the hostname of each of the target hosts during playbook execution using the magic variable {{ inventory_hostname }}.
I then need to extract characters 4 - 6 from the {{ inventory_hostname }} (say 'xyz') such that the second domain to add to the search list is xyz.foo.bar. In bash, this would be obtained with something like:
SERVER=$('hostname':3:3)
env=${SERVER:3:3}
... and the variable 'env' would be equal to 'xyz'.
The playbook works as long as 'xyz' is manually defined.
I am aware that Ansible has regular expression filters which can help with something like this, however I could not figure out a regular expression which does what I need.
For completeness sake, I have tried something like this in ansible:
{{ inventory_hostname|3:3 }}
Any help would be greatly appreciated.
It's almost the same, you can use "{{ inventory_hostname[3:6] }}" to select characters 3 to 6.
For example this task
- debug:
msg: "{{ inventory_hostname[3:6] }}"
Will output
ok: [localhost] => {
"msg": "alh"
}
i have a list like this (shortend for the example)
vars:
cli:
terraform:
bin_name: "terraform"
source_url: "https://releases.hashicorp.com.."
bin_to_copy: "/tmp/{{ bin_name }}"
why is it not possible to access {{ bin_name }} name later? I tried w/ cli.bin_name; item.bin_name; item.key.b....
error is always: FAILED! => {"msg": "'bin_name' is undefined"}
It's not possible. See Can't reference a dict key inside the same dict #50280.
FWIW. Take the common values out of the dictionary. For example
vars:
my_bin_name: "terraform"
cli:
terraform:
bin_name: "{{ my_bin_name }}"
source_url: "https://releases.hashicorp.com.."
bin_to_copy: "/tmp/{{ my_bin_name }}"
tasks:
- name: Find mac-address
ios_command:
provider: "{{ cli }}"
commands:
- show mac add | i d83b
register: sh_mac_res
sh_mac_res is variable contain string like this:
"22 18a9.0530.d83b DYNAMIC Fa0/17"
How can I put 18a9.0530.d83b into a variable?
set_facts:
mac_address: {{ sh_mac_res.stdout }}.........????
What should I use? regex_search or something else?
Use Python split() function and select the second element of the resulting list:
- set_fact:
mac_address: "{{ sh_mac_res.stdout.split()[1] }}"
In my playbook, I'd like to loop over two dictionaries (or one dictionary and one list). One is a list (or dictionary) of Domains, the other one is a dictionary that includes the aws-regions with the corresponding server-IPs to use for the DNS-Entries for latency based routing. I want to set for each domain one DNS-record for each aws-region.
- name: set DNS records for Domains
route53:
zone: "{{ item[0].key }}"
record: "{{ item[0].key }}"
value: "{{ item[1].value.server_ip }}"
region: "{{ item[1].key }}"
identifier: "{{ item[1].key }}"
with_nested:
- "{{ domain_dict }}"
- "{{ aws_dict }}"
With two lists, the example works fine. How do I get it to work using at least one dictionary?
domain_dict: (could be a list as well)
domain_dict:
mytest1.example:
mytest2.example:
mytest3.example:
aws_dict:
aws_dict:
us-east-1:
# some other region-related stuff like ami-id,...
server_ip: 1.2.3.4
us-west-1:
# some other region-related stuff
server_ip: 1.2.3.5
us-west-2:
# some other region-related stuff
server_ip: 1.2.3.6
#all other aws-regions
A custom lookup_plugin is your best bet. Otherwise it'll be an ugly sequence of set_fact.
PS:
While you ordinarily shouldn’t have to, should you wish to write your own ways to loop over arbitrary datastructures, you can read Developing Plugins for some starter information. Each of the above features are implemented as plugins in ansible, so there are many implementations to reference