ansible set_fact if-else failure - if-statement

I am trying to set_fact value based on condition with if-else ,Below is syntax which I use for the if-else condition .
- name: set the server details
set_fact:
ad_server: "{{ '{{ server.westeurope }}' if ('{{ ansible_local.vdc.location }}' == 'westeurope') else '{{ server.eastus2 }}' }}"
ad_server_ip: "{% if'{{ ansible_local.vdc.location }}'=='westeurope' %}{{ server_ip.westeurope }}{% else %}{{ server_ip.eastus2 }}{% endif %}"
- debug:
msg: "{{ ansible_local.vdc.location }},{{ ansible_local.vdc.binaryrepo_url }},{{ ad_server }},{{ ad_server_ip }}"
I have already declared my variable section with the details as mentioned below :
server:
westeurope: WIN030123
eastus2: WIN100270
server_ip:
westeurope: 10.x.x.x
eastus2: 10.x.x.x
my if-else condition fails to get the value of if statement and always gets the value of else condition ..Can someone provide me the correct syntax for this situation.

Using Jinja2 there are different types of markup to define logic and variable expansion and : more information on the Jinja2 Ansible page.
So if you want to do logic (branching) and variable expansion on the same line, like on you first fact setting that will be :
ad_server: "{% if ansible_local.vdc.location == 'westeurope' %}{{ server.westeurope }}{% else %}{{ server.eastus2 }}{% endif %}"
Please try it.

Use Jinja2 if expression:
- name: set the server details
set_fact:
ad_server: "{{ server.westeurope if ansible_local.vdc.location == 'westeurope' else server.eastus2 }}"
ad_server_ip: "{{ server_ip.westeurope if ansible_local.vdc.location == 'westeurope' else server_ip.eastus2 }}"

Related

removing more than a character using cut

So I'm trying to search for Elements using query selector, the problem is, due to the way theses IDs are generated (with the name of regions, stores, and sale type, from the context) some of then includes spaces or dots on them which don't let them be searched.
I have identified the spaces were breaking my searches before and used cut to remove the spaces from IDs.
Is there a way to use cut to remove diferent characters as if I'm using cascaded replaces (in python) or replaceAlls (in JS) to make these ids don't have any spaces or dots? I tried using pipes but it didn't work. how can I do it?
Snippet of the formation of the elements:
{% if data.nivel == "N0" %}
<tr id="family_{{ data.familia_produto|cut:" " }}" class="bu_name_line {{ data.nivel }} title0"
data-level="{{ data.nivel }}" data-family="{{ data.familia_produto }}"
data-regional="{{ data.nome_regional }}" data-segment="{{ data.segmento }}"
data-bu-name="{{ data.nome_filial }}" onclick="show_lines('N1','{{ data.familia_produto }}')">
<td id='bu_name' onmouseenter='hight_light(this)' onmouseleave='hight_light(this)'>
{{ data.familia_produto }}
</td>
{% elif data.nivel == "N1" %}
<tr id="regional_{{ data.familia_produto|cut:" " }}_{{ data.nome_regional|cut:" " }}"
class="bu_name_line {{ data.nivel }} title1 hide" data-level="{{ data.nivel }}"
data-family="{{ data.familia_produto }}" data-regional="{{ data.nome_regional }}"
data-segment="{{ data.segmento }}" data-bu-name="{{ data.nome_filial }}"
onclick="show_lines('N2A','{{ data.familia_produto }}','{{ data.nome_regional }}')">
<td id='bu_name' onmouseenter='hight_light(this)' onmouseleave='hight_light(this)'>
{{ data.nome_regional }}
</td>
Snippet of the selection I'm trying to do to catch this elements:
if (level_name[0] == 'family'){
var forecast_lines = line.parentElement.querySelectorAll(`[id*=regional_${level_name[1]}]`)
}else if (level_name[0] == 'regional'){
var forecast_lines = line.parentElement.querySelectorAll(`[id*=filial_${level_name[1]}_${level_name[2]}]`)
}else if (level_name[0] == 'filial'){
//console.log("entrei aqui 222222222")
var forecast_lines = line.parentElement.querySelectorAll(`[id*=segmento_${level_name[1]}_${level_name[2]}_${level_name[3]}]`)
error:
Uncaught DOMException: Element.querySelectorAll: '[id*=segmento_CAFES_INTERNA_GER.INT.COMERCIAL]' is not a valid selector
Don't know exactly how is your code but it will give you an idea:
should_removed_list = [" ", ".", ",", "="]
for i in should_removed_list:
if str(i) in your_content:
your_content.replace(str(i), "")

I have a Jinja template that only prints the first match of a regex match but I would like it to print all matches

I run a playbook that executes a Cisco command show interfaces and I store that into a variable.
I then jump into a template for further processing to only find Ethernet interfaces and errors.
I find the first match of both interface and error which is fine but I do not find the second match of interface and error in the control environment. The lab device has two interfaces Ethernet0/0 and Ethernet0/1.
Can someone make a suggestion so that I can match on both interfaces and respective errors?
Here is the task:
Blockquote
tasks:
- name: gather interface stats and store in register
ios_command:
commands:
- show interface | section include is up
register: interface_errors
- name: store interface_errors_file
copy:
content: {{interface_errors}}
dest: ./{{inventory_hostname}}_interface_full.txt
- name: deploy template
copy:
content: "{{lookup('template', 'errors.j2') }}"
dest: ./{{inventory_hostname}}_errors.txt
Template:
Blockquote
{% for int in interface_errors.stdout %}
{% set int_name = int | regex_search('Ethernet\d{1,3}\/\d{1,3} is up') %}
{% if 'Ethernet' in int_name | string %}
- Interface: {{int_name}}
{% endif %}
{% endfor %}
{% for int_err in interface_errors.stdout %}
{% set int_errors = int_err | regex_search('\d{1,10000}.input.errors|output.errors') %}
{% if 'errors' in int_errors %}
- Interface Errors: {{int_errors}}
{% endif %}
{% endfor %}

Keep YAML list structure in Ansible templates

Say I have a variable file
---
app1:
environments:
- test
- demo
paths:
- /home/someuser/_env_/*.log
- /var/log/something/*.log
id: _env_
that's included in my playbook like this
---
- hosts: all
become: yes
vars:
apps:
- app1
vars_files:
- ~/vars/app1_vars.yml
tasks:
- name: Update config
template:
src: foo.j2
dest: /home/configurer/test.conf
owner: configurer
group: configurer
mode: '0644'
lstrip_blocks: yes
and the template itself is
{% for app in apps %}
{% for env in vars[app]['environments'] %}
- type: log
enabled: true
paths:
{% for path in vars[app]['paths'] %}
- {{ path | replace("_env_", env) }}
{% endfor %}
fields:
app_id: {{ vars[app]['id'] | replace("_env_", env) }}
{% endfor %}
{% endfor %}
That gives me as output
- type: log
enabled: true
paths:
- /home/someuser/test/*.log
- /var/log/something/*.log
fields:
app_id: test
- type: log
enabled: true
paths:
- /home/someuser/demo/*.log
- /var/log/something/*.log
fields:
app_id: demo
Is there a more compact and nicer way to iterate over the paths variable list and keep the YAML list structure with the -s?
After some experimenting I did the following as an alternative:
Changed the variable file:
---
app1:
environments:
- test
- demo
filebeat_properties:
paths:
- /home/someuser/_env_/*.log
- /var/log/something/*.log
fields:
app_id: _env_
Used to_nice_yaml to pretty-print the config:
{% for app in apps %}
{% for env in vars[app]['environments'] %}
- type: log
enabled: true
{{ vars[app]["filebeat_properties"] | to_nice_yaml(indent=2, width=9999) | indent(2) | replace("_env_", env) }}
{% endfor %}
{% endfor %}

Controlling whitespace in Pebble templates

I'm having a hard time getting the whitespace control the way that I want in a Pebble template. I'm currently generating JSON using Pebble, but this problem and my use case is not specific to JSON (or else I would use a JSON library, such as Jackson instead).
Here's my Pebble template:
"items": {
{% for item in items -%}
"{{ item.name }}": "{{ item.value }}"{% if not loop.last %},{% endif %}
{% endfor %}
},
And, here's the generated output:
"items": {
"item1": "Value 1",
"item2": "Value 2"
},
There are two problems with this:
I had to have the two blank lines in the template (one before the endfor and one after the endfor.
I still end up with the extra blank line in the output before the closing squiggly bracket, i.e. the },.
I'd like for the template to look more like the following:
"items": {
{% for item in items -%}
"{{ item.name }}": "{{ item.value }}"{% if not loop.last %},{% endif %}
{% endfor %}
},
And, I'd like for the resulting output to be:
"items": {
"item1": "Value 1",
"item2": "Value 2"
},
I have tried many combinations of the whilespace control modifier, but no luck on getting the format that I want.
Whitespace control modifier only trim lines. It doesn't remove line feed. The only solution for your use case is to remove blank lines around {% endfor %}

Golang pagination

I need to implement pagination. Actually I have pages array, page param and per_page variable.
In my code:
pages_count := math.Floor(float64(len(pages)) / float64(per_page))
then in template I need something like (pseudocode):
{{ if .page - 2 > 0 }}
{{ $start_page := .page - 2 }}
{{ else }}
{{ $start_page := 1 }}
{{ end }}
{{ if .page + 2 >= .pages_count }}
{{ $finish_page := .page + 2 }}
{{ else }}
{{ $finish_page := .pages_count }}
{{ end }}
<ul>
{{ for $i := $start_page; $i <= $finish_page; ++$i }}
<li {{ if $i == .page }} class="current_page" {{ end }}>
$i
</li>
{{ end }}
</ul>
How to implement this correctly?
Thx
When I work with Java templates (e.g. Velocity), I find that the kinds of template logic you are asking about lead to over-complex templates. The same applied in Go.
My solution is to move logic into the view-model layer and keep the templates rather dumb. This means that the controller and view model have to do a bit more work precomputing the kinds of values that your template shows. The view model is consequently larger - but it's just simple data and is easy to unit-test.
In your specific example, you would keep the for-loop that builds up the <li> list. Everything above the <ul> open tag can be handled in the view model. So the template would just work with some precomputed data.