I want to combine a fact set with set_facts with a string variable and register it as a new variable.
I think, we cannot register a new variable in an Ansible playbook. So can I use set_facts again to combine a previous set_fact with an existing variable?
I am not sure about the syntax here.
Here is an example:
- vars:
list_1: usera,userb,userc
- set_fact:
list_2: "userd,usere,userf"
Now I want to combine both of the string with comma in between and get a variable value like this:
final_list: usera,userb,userc,userd,usere,userf
set_fact:
final_list: "{{ list_1 }},{{ list_2 }}"
or use the string concatenation operator
set_fact:
final_list: "{{ list1 ~ ',' ~ list_2 }}"
Related
I'm working on a playbook to modify a sql script, I need to create a string with a concatenation of conditionals.
this is the conditional structure:
(server.primary_name||'.'||server.arpa_domain like '%server_name%')
This is the ansible task:
- name: Query Conditionals
set_fact:
query_conditionals_list: "{{ query_conditionals_list + [ '(server.primary_name||.||server.arpa_domain like %' + item + '%)' ] }}"
with_items: "{{ server_names }}"
when: "item not in query_conditionals"
loop_control:
label: "{{item}}"
- name: Join names
set_fact:
query_conditionals: "{{query_conditionals_list | join (' OR ')}}"
I believe that I'm not escaping correctly the parentesis and the single qoutes.
Is it possible to escape them?
Thanks
EDIT
I made some modifications.
As suggested by mdaniel, instead of creating the string from the get go, I'm creating first a list and then doing a join with the OR. So that solves my OR problem.
Although, I was not able to escape the single quotes yet
I was able to find a workaround using vars on the ansible task.
While using vars, I was able to maintain the structure I wanted to use and save the single quotes.
- name: Query Conditionals
set_fact:
query_conditionals_list: "{{ query_conditionals_list + [ server_item ] }}"
when: "item not in query_conditionals_list"
loop_control:
label: "{{item}}"
vars:
server_item: "(server.primary_name||'.'||server.arpa_domain like '%{{item}}%')"
with_items: "{{ server_names }}"
I'm trying to get a variable which will contain comma separated items from with_itmes loop as follow:
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: set_fact
set_fact:
foo: "{{ foo }}{{ item }},"
with_items:
- "one"
- "two"
- "three"
vars:
foo: ""
- name: Print the var
debug:
var: foo
It works as expected but what I'm getting at the end is trailing comma.
Is there any way to remove it?
There is a join filter that we can use with lists to concatenate list elements with a given character.
If we are passing the list directly to with_items or loop then we can use loop_control to "extend" some more loop information to get ansible_loop.allitems. Then this can be joined with the join filter.
Example:
- set_fact:
foo: "{{ ansible_loop.allitems|join(',') }}"
loop:
- one
- two
- three
loop_control:
extended: true
Otherwise a more straightforward way is to define a variable with list and use join filter on elements of that variable.
Example:
- set_fact:
foo: "{{ mylist|join(',') }}"
vars:
mylist:
- one
- two
- three
No clue if this is correct way to do but it does the job:
- name: Print the var
debug:
msg: "LIST: {{ foo | regex_replace(',$','') }}"
I have an ansible variable that contains a list of win_uri responses (created by loop).
I want to create a dictionary where each single response body (json) contains a value (title) that I want to use as a key and another one as a value (id).
Right now I am lost.
My current implementation ignores the json - which obviously does not work:
- name: populate folder dictionary
set_fact:
app_folders: "{{ app_folders | default({}) | combine({item.jsonContent.title : item.id}) }}"
with_items: "{{ response.results }}"
I know, that it is possible to read JSON into a variable with the from_json - but I do not know how to combine it with the above code.
If I got your question right, try:
- name: populate folder dictionary
set_fact:
app_folders: "{{ app_folders | default({}) | combine({(item.jsonContent|from_json).title : item.id}) }}"
with_items: "{{ response.results }}"
I've got a role that bootstraps a user's OSX workstation. In it, I need to ensure that xdg variables are set properly, using the following precedence:
defaults/main.yml
user's environment variable
any other value (set in vars, host_vars, command line, etc)
I've tried a couple different approaches, but the basic problem I'm having is that I can't nest variable interpolation, so approach one (and all the others I could think of to try) in defaults/main.yml have failed:
# if the env var doesn't exist, it'll set it to an empty string, doesn't look
# like there is a way to specify the 'default' string that should be used
# xdg_cache_home: "{{ lookup('env','XDG_CACHE_HOME') }}"
# this is just bad syntax, can't have nested '{{ }}'
# xdg_config_home: "{{ lookup('env','XDG_CACHE_HOME') | default("{{ home }}/.cache", true) }}"
# this simply fails to define the variable, i'm not sure why
# xdg_cache_home: "{{ default( lookup('env','XDG_CACHE_HOME'), join(lookup('env', 'HOME', '.cache'))) }}"
The next approach I tried was to just set the defaults using the first method (empty string if empty) and then inspect and set a default value in the roles/myrole/tasks/main.yml:
- name: set default xdg_cache_home
set_fact: xdg_cache_home="{{ join(lookup('env', 'HOME', '/.cache')) }}"
when: "{{ xdg_cache_home }}" == ""
But I can't get that to work either. Any suggestions or advice?
Found the answer in the jinja documentation - using the jinja string concatenation operator (~):
xdg_cache_home: "{{ lookup('env', 'XDG_CACHE_HOME') | default(ansible_user_dir ~ '/.cache', true) }}"
xdg_config_home: "{{ lookup('env', 'XDG_CONFIG_HOME') | default(ansible_user_dir ~ '/.config', true) }}"
xdg_data_home: "{{ lookup('env', 'XDG_DATA_HOME') | default(ansible_user_dir ~ '/.local/share', true) }}"
Say I have two variable like these:
dict:
key1: val1
key2: val2
list:
- item1
- item2
Can I loop over these two variables like below?
- shell: echo {{ item.0.key }} {{ item.1 }}
with_dict: "{{ dict }}"
with_items: "{{ list }}"
I have no idea to loop over these two variables together and don't wanna change the data type of the variables. Is there any way to achieve this kind of loop in ansible?
The combine filter that is introduced in Ansible 2.0 appears to be the closest thing to what you need, but I don't know if it will merge a dict & a list or just two dicts.
Your might need to write your own custom lookup plugin in order to merge these two different variable types.