Get all keys from map in Golang Template without use vars - templates

I have something map by . (point symbol) and I want to print just every key.
I know we can use some:
{{ range $key, $value := . }}{{ $key }}{{end}}
But I cant use var, because I use Docker Compose file which problem withi symbol $.
How I can print all keys without use vars?

Extract the keys and sort them, then feed them into the view, as iterating a map has indeterminate order anyway (which you don’t want).
import "sort"
var m map[int]string
var keys []int
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
Within a range loop, use . to refer to the items being ranged. A new context is created for that loop.
{{ range . }}
{{ . }}
{{ end }}
However I suggest you fix the problem with using the symbol $, you will want to use that. That sounds like the wrong use of Docker Compose files - you could put your golang templates into separate files, or into the go source files themselves if you want a single binary deploy.

Related

How to list only item containing string X in a string Y from a dictionnary in Jinja2

I’m trying to obtain the count of all title containing a specific string from a dictionary in a jinja template.
I have tried many variant with select and other test and haven’t found the right way to do so.
This is not for ansible for which I have found many solutions to fix this issue.
Also the test equalto does not work since I do not have an exact match on the string and doesn’t seem to take regex.
{{ Dictionnary | selectattr("title", "in","MyString") | list | count }}
It seems that the string never gets properly evaluated because it always returns 0.
The selectattr without test return the right number of total titles.
I wonder if we could evaluate it with an if statement somehow.

Merge multiple lists in Jinja2

Is there a way to combine multiple lists in a list in Jinja2 ?
For instance, if I have :
[['foo', 'moo'],['py','jinga','template'],['example'],['stack','overflow']]
I expect to get :
['foo', 'moo','py','jinga','template','example','stack','overflow']
(I don't know the number of lists in the list in advance.)
I already tried to use join() but it doesn't work because I get a string and not a list of strings.
If you don't know upfront the number of sub list, since Jinja won't allow assignment in loops, what you could do is to join back the sub lists via map, then, split it back.
It is not the perfect way, but it does the job.
{{ ([['foo', 'moo'],['py','jinga','template'],['example'],['stack','overflow']] | map('join','|||') | join('|||')).split('|||') }}
You can do a concatenation of lists using the + operator:
['foo','moo'] + ['py','jinga','template'] + ['example'] + ['stack','overflow']
Gives
['foo', 'moo', 'py', 'jinga', 'template', 'example', 'stack', 'overflow']
+ Adds two objects together. Usually the objects are numbers, but if both are strings or lists, you can concatenate them this way.
Source: https://jinja.palletsprojects.com/en/2.11.x/templates/#math
I came here looking for a solution for this problem in ansible, and used β.εηοιτ.βε's solution first. Then I found another solution using json_query and it's flatten projection ([]):
- name: stackoverflow test
hosts: localhost
gather_facts: no
tasks:
- flatten list of lists using json_query's flatten projection
vars:
nested: [["foo", "moo"],["py","jinga","template"],["example"],["stack","overflow"]]
debug:
msg: '{{ nested | json_query("[]") }}'
Not sure if the OP had been using ansible, but if someone else like me ends up here, they might find it useful.

Catch the Interface in the String then Store it in a Variable

Basically my goal is to catch the cisco interfaces (ie. Gi1/0) from the string that I used to store in variable intf. I am puzzled how I am going to construct my regex with set_fact that will catch interface from intf variable.
Based from regex101.com this regex will match Gi1/0 interface:
^\w+(-\w+)?\d+(([\/:]\d+)+(\.\d+)?)?$
I tried below code to catch the interface Gi1/0 for example, and store that in variable storehere, but only encountered errors.
- name: Catch interface only ie. Gi1/0 and store in storehere variable
set_fact:
storehere: "{{ intf | regex_findall(^\w+(-\w+)?\d+(([\/:]\d+)+(\.\d+)?)?$) }}"
This is my full code:
Full Script
Execution W/o Regex
Error W Regex
Your full code seems to imply that there might be multiple lines in the output. Presumably they all follow the same pattern, and the data that you need from each, is just the first column - the interface name? If so, does this fulfill your needs:
- set_fact:
interfaces: "{{ interfaces | default([]) }} + {{ [ item | regex_search('^([^ ])+') ] }}"
loop: "{{ rl00.stdout_lines | first }}"
- debug:
var: interfaces
(Note: in your example, rl00.stdout_lines contains a list, with a list of output lines as its only element. That looks a little odd and I am not sure if there are cases where other elements would be present. This answer should work for the example data you provided, but may run into problems if other elements are returned.)
This:
Loops through the lines contained in the first list contained in your rl00 registered variable
Filters the first non-space chars from the beginning of the string
Adds them as an item in the 'interfaces' list
That should leave you with a list containing interface names. You can then treat them how you like, so for example, if you need them on a single, space separated line, you could then:
- debug:
var: interfaces | join(' ')

String to Int --> Django

[{'age': 1}] being returned something alike to this after a query. This is in my view. Now in my HTML I want to refer to that value returned - in this case '1' if {{}} > 1 ... do something but it cannot do this because Could not parse the remainder: '{{age}}' from '{{age}}'. However if I define a random integer value in my view set it as i.e. 10 I can very easily refer to this variable in my html no problem. I'm presuming it's because it's printing'age' rather than just returning the result from the database. Any solutions to this ? I'm thinking about creating a definition which returns it into a string
You want {% if number > 2 %}. You use {{ number }} to include a variable in the template, but you don't use the double braces inside a template tag.

cts:value-match on xs:dateTime() type in Marklogic

I have a variable $yearMonth := "2015-02"
I have to search this date on an element Date as xs:dateTime.
I want to use regex expression to find all files/documents having this date "2015-02-??"
I have path-range-index enabled on ModifiedInfo/Date
I am using following code but getting Invalid cast error
let $result := cts:value-match(cts:path-reference("ModifiedInfo/Date"), xs:dateTime("2015-02-??T??:??:??.????"))
I have also used following code and getting same error
let $result := cts:value-match(cts:path-reference("ModifiedInfo/Date"), xs:dateTime(xs:date("2015-02-??"),xs:time("??:??:??.????")))
Kindly help :)
It seems you are trying to use wild card search on Path Range index which has data type xs:dateTime().
But, currently MarkLogic don't support this functionality. There are multiple ways to handle this scenario:
You may create Field index.
You may change it to string index which supports wildcard search.
You may run this workaround to support your existing system:
for $x in cts:values(cts:path-reference("ModifiedInfo/Date"))
return if(starts-with(xs:string($x), '2015-02')) then $x else ()
This query will fetch out values from lexicon and then you may filter your desired date.
You can solve this by combining a couple cts:element-range-querys inside of an and-query:
let $target := "2015-02"
let $low := xs:date($target || "-01")
let $high := $low + xs:yearMonthDuration("P1M")
return
cts:search(
fn:doc(),
cts:and-query((
cts:element-range-query("country", ">=", $low),
cts:element-range-query("country", "<", $high)
))
)
From the cts:element-range-query documentation:
If you want to constrain on a range of values, you can combine multiple cts:element-range-query constructors together with cts:and-query or any of the other composable cts:query constructors, as in the last part of the example below.
You could also consider doing a cts:values with a cts:query param that searches for values between for instance 2015-02-01 and 2015-03-01. Mind though, if multiple dates occur within one document, you will need to post filter manually after all (like in option 3 of Navin), but it could potentially speed up post-filtering a lot..
HTH!