I have a dictionary of dictionaries collecting data from openshift using prometheus. Now I intend to add values in all the dictionaries. But some projects don't have quota and hence some pods don't have request/limit set for cpu and memory. I am trying the following and it fails in case the key:value is not there.
If possible I want to use if else such that, if the variable exists then add the variable else use the value as 0.
- name: Total section for Projects
set_fact:
pod_count_total: "{{ (pod_count_total|int) + (item.value.pod_count|int)}}"
total_cpu_request: "{{ (total_cpu_request|float |round(2,'ceil')) + (item.value.cpu_request|float |round(2,'ceil'))}}"
total_cpu_limit: "{{ (total_cpu_limit|float |round(2,'ceil')) + (item.value.cpu_limit|float |round(2,'ceil'))}}"
total_memory_request: "{{ (total_memory_request|float |round(2,'ceil')) + (item.value.memory_request|float |round(2,'ceil'))}}"
total_memory_limit: "{{ (total_memory_limit|float |round(2,'ceil')) + (item.value.memory_limit|float |round(2,'ceil'))}}"
with_dict: "{{all_project}}"
Dictionary of dictionaries is like
ok: [127.0.0.1] => {
"msg": {
"openshift-web-console": {
"cpu_usage": 0.015,
"memory_used": 0.04,
"cpu_request": 0.301,
"memory_request": 0.293,
"pod_count": 3
},
"srv-test": {
"cpu_usage": 0.013,
"memory_used": 0.02,
"pod_count": 5
},
"test": {
"cpu_usage": 0.001,
"memory_used": 0.0,
"pod_count": 1
},
"openshift-monitoring": {
"cpu_limit": 1.026,
"cpu_request": 0.556,
"cpu_usage": 0.786,
"memory_limit": 1.866,
"memory_request": 1.641,
"memory_used": 0.14,
"pod_count": 98
}
}
}
If possible I want to use if else such that, if the variable exists then add the variable else use the value as 0.
The thing you are looking for is the default filter
total_memory_request: "{{ (
total_memory_request | default(0)
| float | round(2,'ceil')
) + (
item.value.memory_request | default(0)
| float | round(2,'ceil')
) }}"
There's a subtlety in that if the variable exists but is the empty string, you'll need to pass in the 2nd parameter to default to have it act in a python "truthiness" way: {{ "" | default(0, true) | float }} -- that might not apply to you, but if it does, you'll be glad to know what that 2nd param does
Related
Given a string list
list:
- a
- b
and a string
str: c
How can be obtained an object list with the same number of elements as the first list with the following structure?:
new_list:
- list_key: a
str_key: c
- list_key: b
str_key: c
Also, I'm using Ansible 2.8
For example
- set_fact:
new_list: "{{ list|
map('regex_replace', '^(.*)$', '{list_key: \\1}')|
map('from_yaml')|
map('combine', {'str_key': str})|
list }}"
I have to loop through a template and create individual files from it in a systematic manner. For example..
Template sample (eg shop_names.conf.j2)
{% for item in shop_names_csv_list %}
# Delete the id
DELETE root/{{item.shop_id}}
# Create the id with contents
PUT root/{{item.shop_id}}
{
"shop_name": "{{item.shop_name}}"
"shop_state": "{{item.shop_state}}"
}
{% endfor %}
I've a CSV in below format which contains data to populate the template
shop_id,shop_name,shop_state
101,Walmart,NY
102,Cosco,MT
103,Apple,DC
I was able to loop through using Ansible and fill it up the template correctly and outputs as shop_names.conf (single file)
The logic I'm using currently is:
- read_csv:
path: shop_names.csv
register: shop_names_csv_list
- name: "Build shop name API endpoints from Template"
template:
src: "{{ item }}"
dest: "{{buildDir}}/{{ item | replace('.j2', '')}}"
with_lines:
- "find {{base_dir_template}} -type f -name '*.j2'"
So currently my output comes as
DELETE root/101
PUT root/101
{
"shop_name": "Walmart"
"shop_state": "NY"
}
# ------- Next Line ------ #
DELETE root/102
PUT root/102
{
"shop_name": "Cosco"
"shop_state": "MT"
}
# ------- Next Line ------ #
DELETE root/103
PUT root/103
{
"shop_name": "Apple"
"shop_state": "DC"
}
# ------- Next Line ------ #
But I was looking to output it as individual files in format of: {{shop_id}}.{{shop_names}}.conf , so that is each DELETE & PUT into single document each per shop_id
So the output, i'm looking for is 3 files namely
101.Walmart.conf
DELETE root/101
PUT root/101
{
"shop_name": "Walmart"
"shop_state": "NY"
}
102.Cosco.conf
DELETE root/102
PUT root/102
{
"shop_name": "Cosco"
"shop_state": "MT"
}
and so on...
Any help to create the template as individual files would be appreciated.
I want to use ansible to merge below 2 dictionary to become 1.
I have been stucking for few days already. Headache.
I have 2 variables now.
1. variable "my_directories":
{
"directoryA": [
"/bar/foo/file1.txt",
"/bar/foo/file2.txt"
],
"directoryB": [
"/bar/baz/file3.txt",
"/bar/baz/file4.txt",
"/bar/baz/file5.txt"
]
}
2. variable "my_filecontents":
{
"/bar/foo/file1.txt": "file1Content",
"/bar/foo/file2.txt": "file2Content",
"/bar/baz/file3.txt": "file3Content",
"/bar/baz/file4.txt": "file4Content",
"/bar/baz/file5.txt": "file5Content"
}
i want to merge it to become:
Result:
variable my_result
{
"directoryA": {
"/bar/foo/file1.txt": "file1Content",
"/bar/foo/file2.txt": "file2Content"
},
"directoryB": {
"/bar/baz/file3.txt": "file3Content",
"/bar/baz/file4.txt": "file4Content",
"/bar/baz/file5.txt": "file5Content"
}
}
The directories and files could be dynamic.
I tried so many codes but still did not work.
Thank you!
The task below does the job
- set_fact:
my_result: "{{ my_result|default({})|
combine({item.0.key: {item.1: my_filecontents[item.1]}},
recursive=True) }}"
with_subelements:
- "{{ my_directories|dict2items }}"
- value
- debug:
var: my_result
gives
"my_result": {
"directoryA": {
"/bar/foo/file1.txt": "file1Content",
"/bar/foo/file2.txt": "file2Content"
},
"directoryB": {
"/bar/baz/file3.txt": "file3Content",
"/bar/baz/file4.txt": "file4Content",
"/bar/baz/file5.txt": "file5Content"
}
}
Is it possible to select which json object to use based on some dynamic criteria?
I have a yml file:
- name: Get data
uri:
url: "foo/get_data/{{item.name}}"
return_content: yes
with_items: "{{stuff_names}}"
register: app_out
- name: Use data
uri:
url: "foo/use_data/item.json[0].id"
method: POST
with_items: "{{ app_out.results }}"
Where the call to foo/get_data/<name> returns a json array with 1 or 2 items:
Sample from foo/get_data/bar1:
[{"id": 1, "type": "x"},{"id": 2, "type": "y"}]
Sample from foo/get_data/bar2:
[{"id": 1, "type": "x"}]
In the "Use data" task is there a way to specify which json object in the array to use based on if an object exists in item or the size of item etc? Right now its hard coded to the first object item.json[0].
For example,
if item contains an object of type "y" then use that object, otherwise use item of type "x".
or
if size of item is > 1, use item of type "x".
EDIT:
Or perhaps even a separate ansible task to prune the registered app_out?
Q: "if item contains an object of type "y" then use that object, otherwise use item of type "x"
A: The play below implements this logic, I think.
- hosts: localhost
vars:
results:
- {"id": 1, "type": "x"}
- {"id": 2, "type": "y"}
- {"id": 3, "type": "z"}
tasks:
- set_fact:
my_list: "{{ results|
selectattr('type', 'defined')|
selectattr('type', 'equalto','y')|list }}"
- set_fact:
my_list: "{{ results|
selectattr('type', 'defined')|
selectattr('type', 'equalto','x')|list }}"
when: my_list|length == 0
- name: Use type y, otherwise use type x
debug:
var: my_list
gives
"my_list": [
{
"id": 2,
"type": "y"
}
]
systems:
- name: Fred
country: DE
- name: Wilma
country: US
- name: Pebbles
country: DE
- name: Dino
country: US
---
# Systems
Countries: {{ page.systems | join(",", "country") }}
I am trying to create a GitBook page with a list of items containing no duplicates. I.e I would want to apply a 'unique' filter or 'distinct' filter in my Nunjucks template for the page. The template needs to process the page variables (YAML). The above template generates the output:
Countries: DE,US,DE,US
I would like it to produce the output
Countries: DE,US
How could I achive that? (Given that 'unique' filter is not supported with Nunjucks.)
You can extend your Nunjucks through Custom filter
const nunjucks = require('nunjucks');
const env = new nunjucks.Environment(/* loaders etc... */);
env.addFilter('unique', arr => arr instanceof Array && arr.filter((e, i, arr) => arr.indexOf(e) == i) || arr);
let out = env.renderString(`{{[1, 2, 3, 2] | unique }}`);
console.log(out);