List of other hosts in ansible, without the current host - ansible

I have these hosts in my hosts.yml file:
all:
hosts:
host1:
name: name1
port: port1
host2:
name: name2
port: port2
host3:
name: name3
port: port3
I want a string with all of my hosts in the hosts.yml file with ports like:
"http://name2:port2, http://name3:port3"
Without the current host (in my example, http://name1:port1).
I want this to be generated for each host when the ansible-playbook is run, and I want to pass it to my app in the startup process like (for host1):
$entrypoint.sh otherUrls="http://name2:port2, http://name3:port3"
I use this code to make the string:
otherUrls: "{%- for host in groups['all'] -%}
{%- if hostvars[host]['name'] is defined -%}
{%- if name != hostvars[host]['name'] -%}http://{{ hostvars[host]['name'] }}:{{ hostvars[host]['port'] }}
{%- if not loop.last -%}\", \"{% endif -%}
{% endif -%}
{% endif -%}
{% endfor -%}"
I made this with jinja2. But I still have an extra ',' at the end of the string for the last host. Are there any ideas to get rid of the problem?

I found a way to my problem without json_query:
{%- set groups_without_this = [] -%}
{% for host in groups['all'] -%}
{% if node_name != hostvars[host]['name'] -%}
{% do groups_without_this.append(host) -%}
{% endif -%}
{% endfor -%}
{%- for host in groups_without_this -%}
{%- if hostvars[host]['nname'] is defined -%}
{%- if name != hostvars[host]['name'] -%}http://{{ hostvars[host]['name'] }}:{{ hostvars[host]['port'] }}
{%- if not loop.last -%}\", \"{% endif -%}
{% endif -%}
{% endif -%}
{% endfor -%}
This code creates a new list without the current node and then constructs the "otherUrls" string.

Related

ansible jinja2: nested dictionary

I'm trying to generate the following list:
list1:127.0.0.1,127.0.0.2
list2:192.168.1.1,192.168.1.254
From this dictionary:
ip_allowed:
list1:
- 127.0.0.1
- 127.0.0.2
list2:
- 192.168.1.1
- 192.168.1.254
Using the following jinja2 Ansible template:
#ZONE HOST(S) OPTIONS
{% for hosts_key, hosts_value in ip_allowed.iteritems() %}
{% set hosts_dict = hosts_value %}
{% for item in hosts_dict %}
{{ hosts_key }} {{ item }}
{%- if loop.first %},{% endif %}
{% endfor %}
{% endfor %}
But I'm getting the following result:
#ZONE HOST(S) OPTIONS
list1 127.0.0.1, list1 127.0.0.2 list2 192.168.1.1, list2 192.168.1.254
I'm not entirely sure I got the exact format you want out of the template but you'll adapt if needed once you get the idea. Just join each ip in the value.
#ZONE HOST(S) OPTIONS
{% for allowed_item in (ip_allowed | dict2items) %}
{{ allowed_item.key }} {{ allowed_item.value | join(',') }}
{% endfor %}

Ansible: Remove last comma in nested loop?

I have the following in a jinja2 template. Essentially I'm looping through a dictionary, picking out the name and if it doesn't start with "sh", I'm adding it to this config. However, I would like to have the server comma separated.
servers = {% for item in list_search_peers.json['entry'] %}{% if not item.name.startswith('sh-') %}{{ item.name }}{% endif %}{% endfor %}
Normally i would do something like:
servers = {% for item in list_search_peers.json['entry'] %}{% if not item.name.startswith('sh-') %}{{ item.name }}{% if not loop.last %},{% endif %}{% endif %}{% endfor %}`
However loop.last won't work because I am filtering out one of the values.
My output is:
servers = x.x.x.x:8089,y.y.y.y:8089,
But i want it without the last ,:
servers = x.x.x.x:8089,y.y.y.y:8089
I was trying {% set } to set a variable but had no luck there.
Filter the list first. For example
- set_fact:
my_list: "{{ list_search_peers.json.entry|
rejectattr('name', 'match', '^sh-(.*)$')|
list }}"
then use it in the template
servers = {% for item in my_list %}{{ item.name }}{% if not loop.last %},{% endif %}{% endfor %}

Ansible jinjia2 template whitespaces control

Question
How do I get the desired output?
Code
yaml
nodeStatusUpdateFrequency:
{% if nodeStatusUpdateFrequency is defined -%}
{{ nodeStatusUpdateFrequency }}
{% else -%}
{%- if nodeStatusUpdate == 'Fast' -%}
4s
{%- elif nodeStatusUpdate == 'Medium' -%}
20s
{%- elif nodeStatusUpdate == 'Low' -%}
1m
{% else -%}
10s
{% endif %}
{%- endif %}
oomScoreAdj: -999
Output:
My current output is:
nodeStatusUpdateFrequency: $x
oomScoreAdj: -999
Desired Output:
My expected output is:
nodeStatusUpdateFrequency: $xoomScoreAdj: -999
Your template is OK. The play below with copy&paste of your template
vars:
nodeStatusUpdateFrequency: "$x"
nodeStatusUpdate: "NONE"
tasks:
- template:
src: test-template.j2
dest: /scratch/test.txt
gives:
# cat /scratch/test.txt
nodeStatusUpdateFrequency: $x
oomScoreAdj: -999
You are simply missing the minus (-) signs on some of your endif control structures. This is doing the job as you expect:
nodeStatusUpdateFrequency:
{%- if nodeStatusUpdateFrequency is defined -%}
{{ nodeStatusUpdateFrequency }}
{%- else -%}
{%- if nodeStatusUpdate == 'Fast' -%}
4s
{%- elif nodeStatusUpdate == 'Medium' -%}
20s
{%- elif nodeStatusUpdate == 'Low' -%}
1m
{%- else -%}
10s
{%- endif -%}
{%- endif -%}
oomScoreAdj: -999

Ansible concat vars to string

I've spent most of the day trying to solve this problem and have thus far failed. I am building some playbooks to automate functions in Splunk, and am attempting to convert a list of hosts from an inventory group E.G.
[search_head]
1.2.3.4
5.6.7.8
My expected (desired) result from the debug output of the play should be:
https://1.2.3.4:8089, https://5.6.7.8:8089
I am attempting to complete this by running the following playbook against a running host:
---
- name: Build search head list to initialize the captain
hosts: search_head
remote_user: ansible
vars:
inventory_file: ./inventory-ec2-single-site
search_head_uri: "{{ lookup('template', './bootstrap-sh-deployer.j2') }}"
pre_tasks:
- include_vars:
dir: 'group_vars'
extensions:
- yml
- yaml
tasks:
- name: dump array
debug:
msg: "{{ search_head_uri }}"`
With the template bootstrap-sh-deployer.j2:
{%- set search_head_uri = [] %}
{% for host in groups['search_head'] %}
{%- if search_head_uri.append("https://{{ host }}:8089") %}
{%- endif %}
{%- if not loop.last %}, {% endif -%}
{%- endfor %}
However, the current play returns search_head_uri: ", " which tells me that the loop is running, but {{ host }} is not resolving.
Once you open a Jinja2 expression or a statement you should use Jinja2 syntax. You cannot nest them (i.e. you can't use {{ }} inside {% %}).
{%- if search_head_uri.append("https://" + host + ":8089") %}
This worked - Combination of the answer above to fix jinja formatting and using hostvars to get to the ansible_nodename.
{%- set search_head_uri = [] %}
{% for host in groups['search_head'] %}
{{ "https://" + hostvars[host]['ansible_nodename'] + ":8089" }}
{%- if not loop.last %}, {% endif -%}
{%- endfor %}

Ansible/Jinja: condition with an undefined statement

I need to iterate over all hosts and generate config file for hosts that are not contained in group somegroup:
{% for host in groups.all if host not in groups['somegroup'] %}
But if somegroup does not exist, it fails (argument of type 'StrictUndefined' is not iterable).
How do I write this correctly to avoid two different for cycles:
{% if groups['somegroup'] is defined %}
{% for host in groups.all if host not in groups['somegroup'] %}
...
{% endfor %}
{% else %}
{% for host in groups.all %}
...
{% endfor %}
{% endif %}
I think you're looking for the default filter:
{% for host in groups.all if host not in groups['somegroup'] | default([]) %}

Resources